如何在C中抛出异常?

htt*_*ret 85 c syntax exception

我把它输入谷歌但只找到了C++中的howtos,

怎么用C做?

Bri*_*ndy 66

在C中没有例外.在C中,错误由函数的返回值,进程的退出值,向进程发出的信号(程序错误信号(GNU libc))或CPU硬件中断(或其他通知错误)通知如果有,则形成CPU)(处理器如何处理除零的情况).

但是,在C++和其他语言中定义的异常.C++中的异常处理在C++标准"S.15异常处理"中指定,C标准中没有等效的部分.

  • @httpinterpret:在C中它"保证"没有例外,就像它"保证"没有模板,没有反射,或没有独角兽一样.语言规范根本没有定义任何这样的东西.但是有setjmp/longjmp,它可用于退出函数而不返回.因此,程序可以根据需要构建自己的异常机制,或者C实现可以定义标准的扩展. (57认同)
  • @Steve:如果你找到一种带有独角兽的语言,请告诉我,我多年来一直在等待这样的事情. (55认同)
  • @ BrianR.Bondy [这里](http://www.unicorncode.com/)是一种带有独角兽的语言(我保证它与C中保证的方式相同) (5认同)
  • 所以在C中它保证不会有例外,如何? (4认同)
  • 在 `.c` 文件中包含 `main` 的程序可以包含一些 C++,因此可以在程序中抛出和捕获异常,但是 C 代码部分将保持对所有这些发生的一无所知,除了异常抛出和捕获通常依赖于用 C 编写的函数,这些函数驻留在 C++ 库中。使用 C 是因为您不能冒险调用执行 `throw` 的函数需要自己抛出异常。不过,可能有一种编译器/库/目标特定的方式来抛出/捕获异常。但是抛出一个类实例会有它自己的问题。 (3认同)

vav*_*ava 31

在C中,您可以使用setjmp()和中longjmp()定义的函数的组合setjmp.h.维基百科的例子

#include <stdio.h>
#include <setjmp.h>

static jmp_buf buf;

void second(void) {
    printf("second\n");         // prints
    longjmp(buf,1);             // jumps back to where setjmp 
                                //   was called - making setjmp now return 1
}

void first(void) {
    second();
    printf("first\n");          // does not print
}

int main() {   
    if ( ! setjmp(buf) ) {
        first();                // when executed, setjmp returns 0
    } else {                    // when longjmp jumps back, setjmp returns 1
        printf("main");         // prints
    }

    return 0;
}
Run Code Online (Sandbox Code Playgroud)

注意:我实际上建议你不要使用它们,因为它们使用C++工作很糟糕(本地对象的析构函数不会被调用),而且很难理解发生了什么.而是返回某种错误.

  • @user4229245我的印象是(轶事)任何“为你做的”都被尽可能地保留在c语言规范之外,特别是为了保持c与裸机和机器编程的相关性,即使是像八位字节这样的现状基础知识也不是不通用,只是我的想法,我不是 c 规范作者 (3认同)
  • 顺便说一句,异常处理是我真正希望在 C11 中结束的事情。尽管普遍认为,它 *** 不*** 需要 OOP 才能正常运行,并且 C 无休止地遭受每个需要 `if()` 的函数调用。我看不出有什么危险;这里还有其他人吗? (2认同)

Luc*_*nes 19

普通的旧C实际上并不支持异常.

您可以使用其他错误处理策略,例如:

  • 返回错误代码
  • 返回FALSE并使用last_error变量或函数.

http://en.wikibooks.org/wiki/C_Programming/Error_handling.


小智 19

C中没有内置的异常机制; 你需要模拟异常及其语义.这通常是依靠setjmp和实现的longjmp.

周围有很多库,我正在实施另一个库.它被称为exceptions4c ; 它是便携式和免费的.您可以查看它,并将其与其他替代方案进行比较,以了解哪种方式最适合您.


wcy*_*wcy 9

C能够抛出C++异常,无论如何它们都是机器代码.例如,在bar.c中

// begin bar.c
#include <stdlib.h>
#include <stdint.h>
extern void *__cxa_allocate_exception(size_t thrown_size);
extern void __cxa_throw (void *thrown_exception, void* *tinfo, void (*dest) (void *) );
extern void * _ZTIl; // typeinfo of long
int bar1()
{
   int64_t * p = (int64_t*)__cxa_allocate_exception(8);
   *p = 1976;
   __cxa_throw(p,&_ZTIl,0);
  return 10;
}
// end bar.c
Run Code Online (Sandbox Code Playgroud)

在a.cc,

#include <stdint.h>
#include <cstdio>
extern "C" int bar1();
void foo()
{
  try{
    bar1();
  }catch(int64_t x){
    printf("good %ld",x);
  }
}
int main(int argc, char *argv[])
{
  foo();
  return 0;
}
Run Code Online (Sandbox Code Playgroud)

编译它

gcc -o bar.o -c bar.c && g++ a.cc bar.o && ./a.out
Run Code Online (Sandbox Code Playgroud)

产量

good 1976
Run Code Online (Sandbox Code Playgroud)

http://mentorembedded.github.io/cxx-abi/abi-eh.html有更多详细信息__cxa_throw.

我不确定它是否可移植,我在Linux上使用'gcc-4.8.2'进行测试.

  • 到底是什么“ _ZTIl”?我在任何地方都找不到对它的引用,这完全是个谜,如何使C代码可以访问std :: type_info。请帮我! (2认同)
  • `_ZTII` 表示`typeinfo for long`,例如`echo '_ZTIl' | c++过滤`。这是 g++ mangling 方案。 (2认同)

Don*_*ows 7

在与MSVC的胜利,__try ... __except ...但它真的很可怕,如果你可以避免它,你不想使用它.更好地说,没有例外.


Joe*_*Joe 7

这个问题是超级老的,但我偶然发现它并认为我会分享一种技术:除以零,或取消引用空指针.

问题只是"如何抛出",而不是如何捕获,甚至如何抛出特定类型的异常.我有一个很久以前的情况,我们需要触发C中的异常才能被C++捕获.具体来说,我们偶尔会报告"纯虚函数调用"错误,需要说服C运行时的_purecall函数抛出一些东西.所以我们添加了自己的_purecall函数除以零,并且繁荣,我们得到了一个我们可以捕获C++的异常,甚至使用一些堆栈乐趣来查看出错的地方.


Joe*_*Joe 6

C没有例外.

有各种hacky实现尝试这样做(例如:http://adomas.org/excc/).