3

このコードに問題があります。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;
}
4

1 に答える 1

9

_Exitデストラクタや関数は実行されずatexit、ただちに終了します。

明らかに、これは RAII に巨大な穴を開けるので、そうしないでください。


同じ出口戦略を維持しながらDon't Do Thatを実装する1つの方法は次のとおりです。

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関数やグローバル デストラクタは説明できません。だからまだそれを避ける.

于 2013-03-27T22:42:17.537 に答える