首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >C语言中的Abort函数

C语言中的Abort函数
EN

Stack Overflow用户
提问于 2015-11-06 19:53:17
回答 5查看 3.6K关注 0票数 5

方案1:

代码语言:javascript
复制
#include<stdio.h>
#include<signal.h>
void handler(int sig);
void main()
{
    printf("PID: %d\n",getpid());
    signal(SIGABRT,handler);
    while(1){
        printf("Hai\n");
        sleep(1);
        abort();
    }
}

void handler(int sig)
{
    printf("Signal handled\n");
}

输出1:

代码语言:javascript
复制
$ ./a.out 
PID: 32235
Hai
Signal handled
Aborted (core dumped)
$

根据引用,abort函数的工作方式与raise(SIGABRT)类似。因此,abort()函数生成的信号是SIGABRT。因此,我创建了上面的程序。

在该程序中,SIGABRT信号被处理。在信号处理程序执行之后,它不会返回到调用它的main函数。为什么在处理程序完成后,它没有返回到main函数?

方案2:

代码语言:javascript
复制
#include<stdio.h>
#include<signal.h>
void handler(int sig);
void main()
{
    printf("PID: %d\n",getpid());
    signal(SIGABRT,handler);
    while(1){
        printf("Hai\n");
        sleep(1);
    }
}

void handler(int sig)
{
    printf("Signal handled\n");
}

输出2:

代码语言:javascript
复制
$ ./a.out 
PID: 32247
Hai
Hai
Hai
Signal handled
Hai
Signal handled
Hai
Hai
^C
$ 

与程序1不同,程序2按预期执行。在上面的程序中,信号通过命令行通过kill命令发送到进程,如下所示。

代码语言:javascript
复制
$ kill -6 32247
$ kill -6 32247

因此,一旦信号发生,处理程序函数就会执行,然后返回到主函数。但是它不会在程序1中发生,为什么它会这样呢?abort函数和SIGABRT是不同的?

EN

回答 5

Stack Overflow用户

发布于 2015-11-06 19:59:19

请参阅来自man 3 abort的这篇文档

这会导致进程异常终止,除非SIGABRT信号被捕获为,并且信号处理程序不返回(参见longjmp(3))。

还有这个:

如果SIGABRT信号被忽略或被返回的处理程序捕获,abort()函数仍将终止进程。它通过恢复SIGABRT的默认配置,然后第二次提高信号来实现这一点。

因此,防止abort()中止程序的唯一方法是从信号处理程序执行longjmp()-ing。

票数 6
EN

Stack Overflow用户

发布于 2015-11-06 20:01:12

Libc实现了abort()。在它们的实现中,abort()检查进程是否仍在运行,因为abort()是在raise(SIGABRT)之后执行的。如果是,那么它就知道用户已经处理了SIGABRT。根据文档,这并不重要,因为进程仍然会退出:

您可以在GLIBC源代码(stdlib/abort.c)中看到确切的实现:

代码语言:javascript
复制
/* Cause an abnormal program termination with core-dump.  */
void
abort (void)
{
  struct sigaction act;
  sigset_t sigs;

  /* First acquire the lock.  */
  __libc_lock_lock_recursive (lock);

  /* Now it's for sure we are alone.  But recursive calls are possible.  */

  /* Unlock SIGABRT.  */
  if (stage == 0)
    {
      ++stage;
      if (__sigemptyset (&sigs) == 0 &&
      __sigaddset (&sigs, SIGABRT) == 0)
    __sigprocmask (SIG_UNBLOCK, &sigs, (sigset_t *) NULL);
    }

  /* Flush all streams.  We cannot close them now because the user
     might have registered a handler for SIGABRT.  */
  if (stage == 1)
    {
      ++stage;
      fflush (NULL);
    }

  /* Send signal which possibly calls a user handler.  */
  if (stage == 2)
    {
      /* This stage is special: we must allow repeated calls of
     `abort' when a user defined handler for SIGABRT is installed.
     This is risky since the `raise' implementation might also
     fail but I don't see another possibility.  */
      int save_stage = stage;

      stage = 0;
      __libc_lock_unlock_recursive (lock);

      raise (SIGABRT);

      __libc_lock_lock_recursive (lock);
      stage = save_stage + 1;
    }

  /* There was a handler installed.  Now remove it.  */
  if (stage == 3)
    {
      ++stage;
      memset (&act, '\0', sizeof (struct sigaction));
      act.sa_handler = SIG_DFL;
      __sigfillset (&act.sa_mask);
      act.sa_flags = 0;
      __sigaction (SIGABRT, &act, NULL);
    }

  /* Now close the streams which also flushes the output the user
     defined handler might has produced.  */
  if (stage == 4)
    {
      ++stage;
      __fcloseall ();
    }

  /* Try again.  */
  if (stage == 5)
    {
      ++stage;
      raise (SIGABRT);
    }

  /* Now try to abort using the system specific command.  */
  if (stage == 6)
    {
      ++stage;
      ABORT_INSTRUCTION;
    }

  /* If we can't signal ourselves and the abort instruction failed, exit.  */
  if (stage == 7)
    {
      ++stage;
      _exit (127);
    }

  /* If even this fails try to use the provided instruction to crash
     or otherwise make sure we never return.  */
  while (1)
    /* Try for ever and ever.  */
    ABORT_INSTRUCTION;
}
票数 2
EN

Stack Overflow用户

发布于 2015-11-06 19:59:11

abort函数发送的SIGABRT信号是真的,但是无论您是否捕获(或忽略)该信号,abort函数仍将退出您的进程。

在链接的手册页面中:

返回值

abort()函数从不返回。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/33566228

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档