能否在C程序终止时调用代码?

4

在C++中,如果我希望在发生错误时调用代码,我可以将代码放在析构函数或try-catch中。

在C语言中是否有类似的技术,使得当程序意外终止时可以调用特定的例程(以清理资源)?

3个回答

7
在C语言中,您可以使用C标准库函数atexit,该函数允许您指定一个不带参数的void函数,在程序终止时调用(概念上,当第一次调用main的结束括号}被执行时)。
在便携式C中,您可以注册多达32个此类函数,并按照它们注册的相反顺序调用它们。
请参见http://en.cppreference.com/w/c/program/atexit

此外,当您显式调用 exit 时,atexit 函数将被触发。 - Basile Starynkevitch

2

如果您想在某些特定行为上调用特定例程,可以尝试处理信号:sigaction(2)

以下是一个例子,其中有人想要处理分段错误: 分段错误处理

一个简单的处理CTRL + c的示例:

#include <signal.h>
#include <stdio.h>

void handle_signal(int);

int main(int argc, char* argv[])
{
    //Setup Signal handling
    struct sigaction sa;
    memset(&sa, 0, sizeof(sa));
    sa.sa_handler = handle_signal;
    sigaction(SIGINT, &sa, NULL);
    ...
}

void handle_signal(int signal)
{
    switch (signal) {
        case SIGINT:
            your_cleanup_function();
            break;
        default:
            fprintf(stderr, "Caught wrong signal: %d\n", signal);
            return;
    }
}

正如评论中所述,有许多不同的signal(7)可供使用。


1
我觉得它没有回答问题,你还应该提到signal(7),最重要的是**signal-safety(7)**。 - Basile Starynkevitch
这个回答和关于atexit的回答是互补的:atexit适用于正常终止,而信号处理程序适用于(大多数)异常终止。 - Sneftel
1
顺便提一下,这也适用于C++,这在问题中已经被解决了。 - Basile Starynkevitch
谢谢@BasileStarynkevitch,还应该提到这两个。 - TacoVox
2
fprintf() 不是异步信号安全的,不能在信号处理程序中安全地调用。请参见 http://pubs.opengroup.org/onlinepubs/9699919799/functions/V2_chap02.html#tag_15_04 - Andrew Henle
显示剩余2条评论

0

C 中没有像析构函数或 try-catch 块这样的功能。 您只需简单地检查函数返回值并清理资源。

通常,C 程序员使用臭名昭著的 goto 语句跳转到清理代码。

void foo()
{
    if (!doA())
        goto exit;
    if (!doB())
        goto cleanupA;
    if (!doC())
        goto cleanupB;

    /* everything has succeeded */
    return;

cleanupB:
    undoB();
cleanupA:
    undoA();
exit:
    return;
}

示例从https://dev59.com/mHVC5IYBdhLWcg3wlyMo#245761复制


你到底在说什么?这似乎与我的答案相矛盾。 - Bathsheba
1
Goto语句并不那么臭名昭著!请查看例如内核编码风格 - TacoVox
虽然 OP 在提到析构函数和 try-catch 时引入了问题,但实际上问题是“在 C 中是否有类似的技术,即如果程序意外终止,我可以调用特定的例程(以清理资源)?” 这个答案并没有回答这个问题。 - Eric Postpischil
3
@EricPostpischil 当OP写出含糊或自相矛盾的问题时,像这个问题一样,回答它们是相当困难的!我喜欢有三个几乎完全不同的答案,基于对OP可能想要什么的三种不同解释。为什么要批评这个答案“没有回答问题”?同样可以批评Bathsheba的答案与try/catch块无关。 - Steve Summit
@SteveSummit:OP的帖子没有任何歧义或自相矛盾之处。该帖子恰好包含一个疑问句,该句清晰明了,说明了OP在程序终止时清理的目标,并且与标题一致。另一句话只是引出问题,并不是一个问题。即使你认为OP想知道C是否有任何本地try-catch块,很明显他们肯定想知道一种在退出时清理的方法,而这个答案并没有回答这个问题。 - Eric Postpischil

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接