在子进程中使用std::string时c++内存泄漏

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

本文关键字:string 内存 泄漏 c++ std 子进程      更新时间:2023-10-16

我对这段代码有问题,valgrind检测std::basic_string中的内存泄漏,我不知道我做错了什么。只有在子进程中使用std::string时才会发生泄漏。你能告诉我问题出在哪里吗?我从来没有在c++中使用过fork(),所以我没有太多的经验。

#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不会运行任何析构函数或atexit函数,它只是立即结束。

显然这会在RAII中打一个巨大的洞,所以不要这样做。


在保持相同退出策略的同时实现Don't Do That的一种方法可能是:

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

在其作用域下的所有析构函数运行之前,它不会提供返回值,给出:

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

但是这仍然不能解释atexit函数或全局析构函数。所以还是要避免这样做

相关文章: