我们应该在C中使用exit()吗? C++中使用了退出>代码>。答案讨论了这是一个不好的主意,主要是因为RAII,例如,如果在代码中的某个地方调用了exit,则不会调用对象的析构函数,因此,例如,如果析构函数打算将数据写入文件,则不会发生这种情况,因为没有调用析构函数

我们应该在C中使用exit()吗? C++中使用了退出>代码>。答案讨论了这是一个不好的主意,主要是因为RAII,例如,如果在代码中的某个地方调用了exit,则不会调用对象的析构函数,因此,例如,如果析构函数打算将数据写入文件,则不会发生这种情况,因为没有调用析构函数,c,C,我很感兴趣的是这种情况在C中是如何发生的。类似的问题在C中也适用吗?我想因为在C中我们不使用构造函数/析构函数,所以C中的情况可能不同。所以在C中使用exit可以吗?例如,我看到在C中有时使用以下函数: void die(const char *message) { if(errno) { perror(message); } else { printf("ERROR: %s\n", message); } e

我很感兴趣的是这种情况在C中是如何发生的。类似的问题在C中也适用吗?我想因为在C中我们不使用构造函数/析构函数,所以C中的情况可能不同。所以在C中使用
exit
可以吗?例如,我看到在C中有时使用以下函数:

void die(const char *message)
{
    if(errno) {
        perror(message);
    } else {
        printf("ERROR: %s\n", message);
    }

    exit(1);
}

您没有构造函数和析构函数,但可以拥有资源(例如文件、流、套接字),正确关闭它们很重要。缓冲区无法同步写入,因此在没有先正确关闭资源的情况下退出程序可能会导致损坏。

是的,可以在C中使用
exit

为确保所有缓冲区正常有序关闭,建议使用此功能
atexit
,了解有关此功能的更多信息

示例代码如下所示:

void cleanup(void){
   /* example of closing file pointer and free up memory */
   if (fp) fclose(fp);
   if (ptr) free(ptr);
}

int main(int argc, char **argv){
   /* ... */
   atexit(cleanup);
   /* ... */
   return 0;
}
现在,无论何时调用
exit
,都会执行函数
cleanup
,该函数可以容纳优雅的关闭、缓冲区、内存等清理。

而不是
abort()
,C中的
exit()
函数被认为是“优雅”的退出

从C11(N1570)7.22.4.4/p2中选择退出功能(强调):

exit
功能导致正常程序终止

该标准在7.22.4.4/p4中还规定:

接下来,刷新所有具有未写入缓冲数据的开放流,所有 打开的流是关闭的,所有文件都是通过
tmpfile
函数创建的 被移除

还值得一看7.21.3/p5文件:

如果
main
函数返回其原始调用者,或者如果
退出
函数调用时,所有打开的文件都将关闭(因此所有输出 流在程序终止前被刷新。其他途径 程序终止,例如调用
中止
函数,不需要 正确关闭所有文件

但是,正如下面的评论中所提到的,您不能假设它将覆盖所有其他资源,因此您可能需要求助于
atexit()
,并分别为它们的发布定义回调。事实上,正如7.22.4.2/p2中所述,这正是atexit()的意图,atexit函数:

atexit
函数将
func
指向的函数注册为 在正常程序终止时无参数调用


值得注意的是,C标准没有明确说明分配存储持续时间的对象应该发生什么(即
malloc()
),因此要求您了解在特定实现中是如何做到的。对于现代的、面向主机的操作系统,系统很可能会处理它,但您可能仍然希望自己处理它,以便使内存调试器(如.

main()
以外的函数中避免退出
的一个原因是代码可能会脱离上下文。请记住,退出是一种非本地控制流。就像不可追踪的异常一样

例如,您可以编写一些存储管理函数,这些函数在出现严重磁盘错误时退出。然后有人决定把它们搬进图书馆。从库中退出会导致调用程序在不合适的状态下退出,这可能是它没有准备好的

或者您可以在嵌入式系统上运行它。无处可退出,整个过程在
中运行,而(1)
循环在
main()
中。它甚至可能没有在标准库中定义。

使用
exit()
可以 尚未提及的代码设计的两个主要方面是“线程”和“库”

在单线程程序中,在为实现该程序而编写的代码中,可以使用
exit()
。我的程序经常在出现问题并且代码无法恢复时使用它

但是… 但是,调用
exit()
是无法撤消的单方面操作。这就是为什么“线程”和“库”都需要仔细考虑的原因

线程程序 如果一个程序是多线程的,那么使用
exit()
是一个戏剧性的动作,它会终止所有线程。退出整个程序可能是不合适的。退出线程并报告错误可能是合适的。如果您知道程序的设计,那么单方面退出可能是允许的,但一般来说,这是不可接受的

库代码 “了解程序设计”条款也适用于库中的代码。通用库函数调用
exit()
很少是正确的。如果一个标准的C库函数仅仅因为一个错误而无法返回,那么您将有理由感到不安。(显然,像
exit()
\u exit()
quick\u exit()
abort()
这样的函数是不返回的;这是不同的。)因此,C库中的函数要么“不能失败”,要么以某种方式返回错误指示。如果编写代码进入通用库,则需要仔细考虑代码的错误处理策略。它应该与计划使用它的程序的错误处理策略相适应,或者可以配置错误处理

我有一系列库函数(在标题为“stderr.h”
的包中,这个名称非常简单),它们在用于错误报告时打算退出
unsigned char cbShowDataThenExit( unsigned char *data, unsigned short dataSz,unsigned char status)
{

    printf("cbShowDataThenExit with status %X (dataSz %d)\n", status, dataSz);
    printf("status:%d\n",status);
    printArray(data,dataSz);
    cleanUp();
    exit(0);
}