fork with invalid command cause a memory leak in valgrind

旧街凉风 提交于 2019-12-05 19:14:28

That is expected. When execve() can't execute command, it returns control to your code, and than you exit and never free memory from strdup().

When execve succeeds, the whole file image is replaced, and nothing remains of the memory allocated with strdup().

You shouldn't care about this "leak", because it's just your process terminating abnormally. You are not expected to carefully free your resources when you need to just print an error message and exit. The OS will free all outstanding resources.

If you are still concerned about this for some reason, try replacing exit(0) with return -1;. In a real program you would never use exit, but only normal return paths that free allocated resources. In C++, use RAII and throw an exception when you need to exit abnormally. Here is your program converted to RAII style:

#include <cstdlib>
#include <cstdarg>
#include <cerrno>
#include <vector>
#include <string>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <stdexcept>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

// This function should be standard in some kind of POSIX C++ library
void execvp(const std::string& program, const std::vector<std::string>& args)
{
    std::vector<const char*> real_argv(args.size()+1);
    for (const std::string& s : args)
        real_argv.push_back(s.c_str());
    real_argv.push_back(nullptr);
    // have to use const_cast because of the broken const model of C
    execvp(program.c_str(), const_cast<char**>(real_argv.data()));
    throw std::runtime_error((std::string("Could not execvp ") + args[0]).c_str());
}

int external_cmd(const std::string& program, const std::vector<std::string>& args)
{
    int pid;

    if ((pid = fork()) == -1)
        return -1;

    if (pid == 0) {
        /* child */
        execvp(program, args);

    } else if (pid < 0)
        return -1;

    int status;
    while (wait(&status) != pid);

    return 0;
}

int main ()
{
    try {
        std::vector<std::string> args;
        args.push_back("tawtaw");
        args.push_back("-a");

        std::string s("12345678"); // RAII

        /* fork call */
        external_cmd(args[0], args);

        return EXIT_SUCCESS;
    } catch (std::exception& e) {
        std::cerr << e.what() << ". Exiting.\n";
        return EXIT_FAILURE;
    } catch ( ... ) {
        std::cerr << "Unexpected error. OS message is: " << strerror(errno) << ". Exiting.\n";
        return EXIT_FAILURE;
    }
}
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!