简体   繁体   中英

C++ memory leak while using std::string in child process

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;
}

_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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM