我们应该在子进程中使用 exit 还是 return

Should we use exit or return in child process

说我用fork创建了一个子进程。这是一个例子:

pid_t pid=fork();
if (pid==0) /* child */
{
    // do something
    exit(0); // _exit, exit or return????
}
else /* parrent */
{
    wait(nullptr);
    return 0;
}

我见过很多 fork 的例子。其中一些使用 _exit 来终止子进程以避免刷新 I/O 缓冲区,其他人使用 exit 来终止子进程。但他们中没有人使用 return。据我了解,_exitexit 不会自动调用析构函数,所以在子进程中调用 return 而不是 exit 更好吗?或者因为我见过的所有例子都是 C,而不是 C++,所以他们不需要担心析构函数?

如果您正在寻找子进程的退出代码,您可以使用 return,只是说进程 运行 并执行 correctly/not。与您在程序中对主要功能所做的相同。否则,只需使用 exit 停止进程 运行。

fork 会复制整个过程,它不等同于用新的主函数启动一个线程。 返回将简单地从当前函数 return 并且子函数的执行将在封闭函数中继续。

因此在您的代码片段中,您必须终止子进程,否则它将 "escape"。您可以通过调用 exit()std::terminate() 来实现。在这两种情况下都没有调用析构函数。不要混用两种不同的语言。

如果你真的需要在子进程中调用析构函数,抛出异常并在main中捕获它。这将正确展开堆栈。

您可以使用 _exitexit,但不应使用 return。当您分叉 child 时,您保留了整个调用堆栈作为分叉 child 的一部分。因此,如果您使用 return,您最终会返回整个程序,可能会继续执行其他任务,这几乎肯定不是您想要的。

例如,如果您有这样的片段:

int get_value()
{
    pid_t pid;
    if (!(pid = fork())) {
        int x = 0;
        // do something with x.
        exit(x);
    }
    else {
        int status;
        wait(&status);
        return status;
    }
}

int main()
{
    int value = get_value();
    switch (get_value()) {
        case 0:
            // call f
            break;
        case 255 << 8:
            // call g
            break;
    }
}

您最终可能会调用 fg 或使用 return 进行其他工作,这绝对不是您想要的。

如果您调用 _exit,则不会调用使用 atexit 注册的函数。在线程环境中这是正确的做法。如果您不在线程环境中工作,并且您没有在 atexit 注册任何处理程序,那么它们在功能上应该是等效的。

如果要调用 child 进程中的析构函数,请将 child 进程代码放在它自己的函数中,并让它的变量在超出范围时自动销毁。 exit 不会为您销毁 objects,这很好,因为通常您不想在 child 进程中销毁在 parent 进程中创建的 objects。

Exit命令在任何情况下都应避免使用,除非结束程序的执行。对于其他任何事情,我会使用 return.