我们应该在C中使用exit()吗? C++中使用了退出>代码>。答案讨论了这是一个不好的主意,主要是因为RAII,例如,如果在代码中的某个地方调用了exit,则不会调用对象的析构函数,因此,例如,如果析构函数打算将数据写入文件,则不会发生这种情况,因为没有调用析构函数
我很感兴趣的是这种情况在C中是如何发生的。类似的问题在C中也适用吗?我想因为在C中我们不使用构造函数/析构函数,所以C中的情况可能不同。所以在C中使用我们应该在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
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);
}