如何在C中抛出异常?

问题描述 投票:75回答:10

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

怎么用C做?

c exception syntax
10个回答
61
投票

在C中没有例外。在C中,错误由函数的返回值,进程的退出值,向进程发出的信号(Program Error Signals (GNU libc))或CPU硬件中断(或者如果存在CPU的其他通知错误)通知)(How processor handles case of division by zero)。

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


2
投票

C不支持例外。您可以尝试使用Visual Studio或G ++将C代码编译为C ++,并查看它是否按原样编译。大多数C应用程序将在没有重大更改的情况下编译为C ++,然后您可以使用try ... catch语法。


28
投票

在C中你可以使用setjmp()中定义的longjmp()setjmp.h函数的组合。 Example from Wikipedia

#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;
}

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


18
投票

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

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

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

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


16
投票

C中没有内置的异常机制;你需要模拟异常及其语义。这通常是通过依靠setjmplongjmp来实现的。

周围有很多库,我正在实施另一个库。它被称为exceptions4c;它是便携式和免费的。你可以看看它,并将它与other alternatives进行比较,看看哪个最适合你。


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

在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;
}

编译它

gcc -o bar.o -c bar.c && g++ a.cc bar.o && ./a.out

产量

good 1976

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

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


6
投票

C没有例外。

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


6
投票

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

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


6
投票

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


3
投票

正如许多线程中所提到的,执行此操作的“标准”方法是使用setjmp / longjmp。我向https://github.com/psevon/exceptions-and-raii-in-c发布了另一个这样的解决方案据我所知,唯一依赖于自动清理已分配资源的解决方案。它实现了独特的共享智能指针,并允许中间函数让异常通过而无需捕获并仍然可以正确清理其本地分配的资源。

© www.soinside.com 2019 - 2024. All rights reserved.