我把它输入谷歌但只找到了C ++中的howtos,
如何在C中完成?
答案 0 :(得分:61)
C中没有例外。在C中,错误由函数的返回值,进程的退出值,向进程发出信号(Program Error Signals (GNU libc))或CPU硬件中断(或其他通知)通知如果存在错误,则表示CPU(How processor handles case of division by zero)。
但是用C ++和其他语言定义的异常。 C ++中的异常处理在C ++标准“S.15异常处理”中指定,C标准中没有等效的部分。
答案 1 :(得分: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 ++工作很糟糕(本地对象的析构函数不会被调用)而且它真的很难了解发生了什么。而是返回某种错误。
答案 2 :(得分:18)
普通旧C实际上并不支持异常。
您可以使用其他错误处理策略,例如:
FALSE
并使用last_error
变量或函数。请参阅http://en.wikibooks.org/wiki/C_Programming/Error_handling。
答案 3 :(得分:16)
C中没有内置异常机制;你需要模拟异常及其语义。这通常取决于setjmp
和longjmp
。
周围有很多图书馆,我正在实施另一个图书馆。它被称为exceptions4c;它是便携式和免费的。您可以查看它,并将其与other alternatives进行比较,看看哪个最适合您。
答案 4 :(得分: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
。
我不确定它是否可移植,我用&#39; gcc-4.8.2&#39;进行测试。在Linux上。
答案 5 :(得分:6)
C没有例外。
有各种hacky实现尝试这样做(例如:http://adomas.org/excc/)。
答案 6 :(得分:6)
在胜利时使用 MSVC 有__try ... __except ...
,但这真的很糟糕,如果你可以避免它,你不想使用它。最好说没有例外。
答案 7 :(得分:6)
这个问题已经超级老了,但我偶然发现它并认为我会分享一种技术:除以零,或取消引用空指针。
问题只是“如何投掷”,而不是如何捕获,甚至如何抛出特定类型的异常。我有一个很久以前的情况,我们需要触发C中的异常才能被C ++捕获。具体来说,我们偶尔会报告“纯虚函数调用”错误,需要说服C运行时的_purecall函数抛出一些东西。所以我们添加了自己的_purecall函数除以零,并且繁荣,我们得到了一个我们可以捕获C ++的异常,甚至使用一些堆栈乐趣来查看出错的地方。
答案 8 :(得分:3)
如众多线索所述,&#34;标准&#34;这样做的方法是使用setjmp / longjmp。我向https://github.com/psevon/exceptions-and-raii-in-c发布了另一个这样的解决方案 据我所知,这是唯一依赖于自动清理已分配资源的解决方案。它实现了独特的共享智能指针,并允许中间函数允许异常通过,而不会捕获并仍然可以正确清理其本地分配的资源。
答案 9 :(得分:2)
C不支持例外。您可以尝试使用Visual Studio或G ++将C代码编译为C ++,并查看它是否按原样编译。大多数C应用程序将在没有重大更改的情况下编译为C ++,然后您可以使用try ... catch语法。
答案 10 :(得分:0)
如果您使用快乐路径设计模式(例如,针对嵌入式设备)编写代码,则可以使用运算符“ goto”来模拟异常错误处理(也称为延迟或最终仿真)。
int process(int port)
{
int rc;
int fd1;
int fd2;
fd1 = open("/dev/...", ...);
if (fd1 == -1) {
rc = -1;
goto out;
}
fd2 = open("/dev/...", ...);
if (fd2 == -1) {
rc = -1;
goto out;
}
// Do some with fd1 and fd2 for example write(f2, read(fd1))
rc = 0;
out:
//if (rc != 0) {
(void)close(fd1);
(void)close(fd2);
//}
return rc;
}
它实际上不是异常处理程序,但是它为您提供了一种在功能退出时处理错误的方法。
P.S。您应该小心地仅在相同或更大范围内使用goto,切勿跳转变量声明。
答案 11 :(得分:0)
Implementing exceptions in c由Eric Roberts
汉森C Interfaces and Implementations的第4章。
A Discipline of Error Handling,道格·摩恩(Doug Moen)
Implementing Exceptions in C(详细介绍E Roberts的文章)