3

I'm having problem with this piece of code, valgrind detects memory leaks in std::basic_string and I don't know what am I doing wrong. The leak is only when std::string is used in child process. Could you please tell me, where the problem is? I've never used fork() in C++ before so I don't have much exprience.

#include <iostream> #include <string> #include <cerrno> #include <cstdio> #include <cstdlib> #include <unistd.h> #include <sys/wait.h> int main(int argc, char *argv[]) { pid_t childPid = fork(); if (childPid == -1) { perror("fork"); return EXIT_FAILURE; } else if (childPid == 0) { std::cout << "Child PID: " << getpid() << std::endl; std::string str("something"); //valgrind detects mem leak here _Exit(EXIT_SUCCESS); } else { //std::string str("something"); //but not here } waitpid(-1, 0, 0); return EXIT_SUCCESS; } 
2
  • 3
    Instead of calling _Exit try returning like you do at the end of the function. Commented Mar 27, 2013 at 22:39
  • 3
    Does _Exit prevent the stack from unwinding? That might prevent the std::string destructor from running. Commented Mar 27, 2013 at 22:40

1 Answer 1

9

_Exit will not run any destructors or atexit functions, it simply ends immediately.

Obviously this punches a giant hole through RAII, so Don't Do That.


One way of implementing Don't Do That while maintaining the same exit strategy might be:

template <typename Func, typename... Args> int wrap_cpp_code(Func&& func, Args&&.. args) { try { return std::forward<Func>(func)(std::forward<Args>(args)...); } catch (...) { return EXIT_FAILURE; } } 

Which won't cough up an return value until all destructors under its scope are run, giving:

int child_main(int argc, char *argv[]) { std::cout << "Child PID: " << getpid() << std::endl; std::string str("something"); return EXIT_SUCCESS; } int main(int argc, char *argv[]) { pid_t childPid = fork(); if (childPid == -1) { perror("fork"); return EXIT_FAILURE; } else if (childPid == 0) { int ret = wrap_cpp_code(child_main, argc, argv); _Exit(ret); } else { /* int ret = wrap_cpp_code(xyz, argc, argv); */ } waitpid(-1, 0, 0); return EXIT_SUCCESS; } 

But this still fails to account for atexit functions or global destructors. So still Avoid Doing That.

Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.