1. 主页
  2. 文档
  3. C语言教程
  4. C语言函数
  5. exit(), abort() 和 assert()

exit(), abort() 和 assert()

exit()

void exit ( int status ); 

exit() 正常终止进程。
status:返回给父进程的状态值。通常,状态值为 0 或 EXIT_SUCCESS 表示成功,任何其他值或常量 EXIT_FAILURE 用于表示错误。exit() 执行以下操作。
* 刷新未写入的缓冲数据。
* 关闭所有打开的文件。
* 删除临时文件。
* 返回一个整数退出状态给操作系统。

C 标准atexit()函数可用于自定义 exit() 以在程序终止时执行其他操作。

exit的使用示例。

/* exit example */
#include <stdio.h>
#include <stdlib.h>

int main ()
{
FILE * pFile;
pFile = fopen ("myfile.txt", "r");
if (pFile == NULL)
{
printf ("Error opening file");
exit (1);
}
else
{
/* file operations here */
}
return 0;
}

当调用 exit() 时,属于该进程的所有打开的文件描述符都将关闭,并且该进程的任何子进程都由进程 1 init 继承,并且进程父进程会收到一个 SIGCHLD 信号。

exit() 背后的奥秘在于它只需要 0 – 255 范围内的整数参数。超出范围的退出值可能会导致意外退出代码。大于 255 的退出值返回退出代码模 256。
例如,退出 9999 给出退出代码 15 即 (9999 % 256 = 15)。

下面是说明上述事实的 C 实现:

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/wait.h>

int main(void)
{
pid_t pid = fork();

if ( pid == 0 )
{
exit(9999); //passing value more than 255
}

int status;
waitpid(pid, &status, 0);

if ( WIFEXITED(status) )
{
int exit_status = WEXITSTATUS(status);

printf("Exit code: %d\n", exit_status);
}

return 0;
}

输出:

Exit code: 15

请注意,由于禁用了 fork(),上述代码可能不适用于在线编译器。

解释:这是 8 位整数溢出的影响。在 255(所有 8 位设置)之后为 0。
因此输出为“退出代码模 256”。上面的输出实际上是值 9999 和 256 的模数,即 15。

abort()

void abort ( void );

与 exit() 函数不同,abort() 可能不会关闭打开的文件。它也可能不会删除临时文件,也可能不会刷新流缓冲区。此外,它不会调用用atexit()注册的函数。

该函数实际上通过引发 SIGABRT 信号来终止进程,并且您的程序可以包含一个处理程序来拦截该信号(请参阅this)。

所以像下面这样的程序可能不会将“Geeks for Geeks”写入“tempfile.txt”

#include<stdio.h>
#include<stdlib.h>
int main()
{
FILE *fp = fopen("C:\\myfile.txt", "w");

if(fp == NULL)
{
printf("\n could not open file ");
getchar();
exit(1);
} 

fprintf(fp, "%s", "Geeks for Geeks");

/* ....... */
/* ....... */
/* Something went wrong so terminate here */ 
abort();

getchar();
return 0; 
} 

如果我们想确保将数据写入文件和/或刷新缓冲区,那么我们应该使用 exit() 或包含 SIGABRT 的信号处理程序。

assert()

void assert( int expression );

如果表达式计算结果为 0(假),则表达式、源代码文件名和行号被发送到标准错误,然后调用 abort() 函数。如果标识符 NDEBUG(“无调试”)是用#define NDEBUG 定义的,那么宏断言什么也不做。

常见的错误输出形式为:

Assertion failed: expression, file filename, line line-number

#include<assert.h>

void open_record(char *record_name)
{
assert(record_name != NULL);
/* Rest of code */
}

int main(void)
{
open_record(NULL);
}

 

这篇文章对您有用吗? 1