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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With