Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C++ program memory leak on SIGINT

I have a program, that used as socket client, here is code

#include <stdio.h>
#include <signal.h>
#include <iostream>
#include <stdlib.h>
#include <string.h>
#include <string>
#include <sys/socket.h>
#include <netdb.h>

using namespace std;

void signalHandler(const int signal) {
    cout << "SIGINT handled" << endl;
    exit(EXIT_SUCCESS);
}

void error(const char *msg) {
    perror(msg);
    exit(0);
}

const string readStr(int descriptor) {
    int n = 0;
    string cmd = "";

    char buffer[256];
    memset(buffer, 0, sizeof(buffer));

    while ((n = read(descriptor, buffer, 255)) != 0) {
        if (n < 0) {
            error("Error reading string");
        }

        // full string - just copy
        if (n == 255) {
            cmd += buffer;
            memset(buffer, 0, sizeof(buffer));
        }
        else {
            cmd += buffer;
            break;
        }
    }

    return cmd;
}

int main(int argc, char** argv) {
    signal(SIGINT, signalHandler);

    int fd, port = (argc >= 3 ? atoi(argv[2]) : 11212), n;
    fd = socket(AF_INET, SOCK_STREAM, 0);
    if (fd < 0) {
        error("ERROR opening socket");
    }

    struct hostent *server = (argc >= 2 ? gethostbyname(argv[1]) : gethostbyname("localhost"));
    if (server == NULL) {
        error("ERROR no such host");
    }

    struct sockaddr_in addr;
    memset(&addr, 0, sizeof(addr));

    addr.sin_family = AF_INET;
    bcopy(server->h_addr, &addr.sin_addr.s_addr, server->h_length);
    addr.sin_port = htons(port);

    if (connect(fd, (struct sockaddr*)&addr, sizeof(addr)) < 0) {
        error("ERROR connecting");
    }

    string tmp;
    while (1) {
        cout << "Please enter the message: \n< " << flush;
        tmp = readStr(0);
        n = send(fd, tmp.c_str(), tmp.size(), 0);
        if (n < 0) {
            perror("ERROR writing to socket");
        }

        tmp = readStr(fd);
        cout << "> " << tmp << endl;
    }
    close(fd);

    return EXIT_SUCCESS;
}

When I send SIGNINT to process (CTRL + C) valgrind says:

^CSIGINT handled
==3798==
==3798== HEAP SUMMARY:
==3798==     in use at exit: 39 bytes in 1 blocks
==3798==   total heap usage: 45 allocs, 44 frees, 4,778 bytes allocated
==3798==
==3798== 39 bytes in 1 blocks are possibly lost in loss record 1 of 1
==3798==    at 0x402471C: operator new(unsigned int)
(vg_replace_malloc.c:255)
==3798==    by 0x40DBB64: std::string::_Rep::_S_create(unsigned int,
unsigned int, std::allocator const&) (in
/usr/lib/libstdc++.so.6.0.15)
==3798==    by 0x1BFF403: ???
==3798==
==3798== LEAK SUMMARY:
==3798==    definitely lost: 0 bytes in 0 blocks
==3798==    indirectly lost: 0 bytes in 0 blocks
==3798==      possibly lost: 39 bytes in 1 blocks
==3798==    still reachable: 0 bytes in 0 blocks
==3798==         suppressed: 0 bytes in 0 blocks
==3798==
==3798== For counts of detected and suppressed errors, rerun with: -v
==3798== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 20 from 9)

If program exit correctly, for example if replate while(1) by int i = 0; while(i++ <= 2), than no memory leaks

So can anybody help me to fix this?

like image 243
azat Avatar asked Sep 07 '26 05:09

azat


1 Answers

When you call std::exit from the signal handler, the stack is not unwound and local variables like the std::string object tmp in main are not destroyed.

Since tmp isn't destroyed before the program terminates, the memory that it allocated is never freed, hence the leak.

like image 127
James McNellis Avatar answered Sep 09 '26 19:09

James McNellis