3
votes

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?

1
@unapersson: Wrong, see James McNellis's answer.orlp
@nightcracker All the memory is freed when the process terminates. That is not what I (and most other people) call a memory leak, which is where a block of memory in a running program becomes inaccessible.user2100815
@azat, This is just a nit-pick. It's customary to use 0 as the exit code for successful operations, and non-zero for some sort of error.Jason D
These are not memory leaks. BTW your use of cout from the signal handler is unsafe. So is exit. Only _Exit would be safe. Or you could just raise another signal to exit.R.. GitHub STOP HELPING ICE
@R.. could yor give me an example?azat

1 Answers

4
votes

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.