📜  exit(),abort()和assert()

📅  最后修改于: 2021-05-26 01:37:09             🧑  作者: Mango

出口()

void exit ( int status ); 

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

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

使用出口示例。

/* exit example */
#include 
#include 
   
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范围内的整数args。超出范围的退出值可能会导致意外的退出代码。大于255的退出值将返回以256为模的退出代码。
例如,出口9999给出的出口代码为15,即(9999%256 = 15)。

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

#include 
#include 
#include 
#include 
#include 
  
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信号来终止该过程,并且您的程序可以包括用于拦截该信号的处理程序(请参见此内容)。

因此,如下所示的程序可能不会将“ Geeks for Geeks”写入“ tempfile.txt”

#include
#include
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包括信号处理程序。

断言()

void assert( int expression );

如果expression的计算结果为0(假),则将表达式,源代码文件名和行号发送到标准错误,然后调用abort()函数。如果使用#define NDEBUG定义了标识符NDEBUG(“无调试”),则宏断言不执行任何操作。

常见错误输出的形式为:

断言失败:表达式,文件文件名,行行号

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

相关文章:
C和C++中的exit()与_Exit()

参考:
退出码
http://www.cplusplus.com/reference/clibrary/cstdlib/abort/
http://www.cplusplus.com/reference/clibrary/cassert/assert/
http://www.acm.uiuc.edu/webmonkeys/book/c_guide/2.1.html
https://www.securecoding.cert.org/confluence/display/seccode/ERR06-C.+了解+终止+行为+断言+断言%28%29 +和+中止%28%29
https://www.securecoding.cert.org/confluence/display/seccode/ERR04-C.+选择+一个+适当的+终止+策略

想要从精选的最佳视频中学习和练习问题,请查看《基础知识到高级C的C基础课程》。