我在Google中输入了此字词,但只在C ++中找到了howtos,
用C怎么做?
我在Google中输入了此字词,但只在C ++中找到了howtos,
用C怎么做?
Answers:
C中没有异常。在C中,错误是通过函数的返回值,进程的退出值,发给进程的信号(程序错误信号(GNU libc))或CPU硬件中断(或其他通知)来通知的(如果有的话)从CPU产生错误)(处理器如何处理被零除的情况)。
例外是用C ++和其他语言定义的。C ++中的异常处理在C ++标准“ S.15异常处理”中指定,C标准中没有等效部分。
main
的.c
文件可以包含一些C ++,因此异常可能会被抛出,并夹在程序中,但C代码部分仍将无知这一切的要去除了异常抛出的和捕获往往依赖于C写的函数驻留在C ++库中。之所以使用C,是因为您不必冒险调用throw
需要自己抛出异常的函数。但是,可能存在编译器/库/目标特定的引发/捕获异常的方式。但是抛出一个类实例将有它自己的问题。
在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;
}
注意:实际上,我建议您不要使用它们,因为它们无法在C ++上正常工作(不会调用本地对象的析构函数),并且确实很难理解发生了什么。而是返回某种错误。
普通的旧C实际上并不本地支持异常。
您可以使用其他错误处理策略,例如:
FALSE
并使用last_error
变量或函数。请参阅http://en.wikibooks.org/wiki/C_Programming/Error_handling。
GetLastError()
在Windows API中。
C中没有内置的异常机制。您需要模拟异常及其语义。这通常是依靠setjmp
和来实现的longjmp
。
周围有很多库,而我正在实现另一个。它称为exceptions4c;它是便携式且免费的。您可以查看一下,然后将其与其他替代方案进行比较,以找出最适合您的方案。
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”对其进行了测试。
_ZTII
手段typeinfo for long
,例如echo '_ZTIl' | c++filt
。这是g ++处理方案。
这个问题太老了,但我偶然发现了这个问题,以为我会分享一种技术:除以零或取消引用空指针。
问题仅是“如何引发”,而不是如何捕捉甚至如何引发特定类型的异常。我很久以前就遇到过这样的情况,我们需要触发C的异常才能被C ++捕获。具体来说,我们偶尔会报告“纯虚函数调用”错误,因此需要说服C运行时的_purecall函数抛出某些错误。因此,我们添加了自己的_purecall函数,该函数除以零,再加上繁荣,我们得到了一个例外,可以捕获C ++,甚至可以利用一些堆栈乐趣来查看问题出在哪里。
在带有MSVC的Win上,__try ... __except ...
它确实很可怕,如果可以避免的话,您就不想使用它。最好说没有例外。
C没有例外。
有许多尝试实现此目的的hacky实现(一个示例,位于:http : //adomas.org/excc/)。
如许多线程中所述,执行此操作的“标准”方法是使用setjmp / longjmp。我在https://github.com/psevon/exceptions-and-raii-in-c中发布了另一个这样的解决方案,据 我所知,这是唯一依靠自动清除分配的资源的解决方案。它实现了唯一且共享的智能指针,并允许中间函数让异常通过而不会捕获,并且仍可以正确清理其本地分配的资源。
C不支持异常。您可以尝试使用Visual Studio或G ++将C代码编译为C ++,然后查看它是否可以原样编译。大多数C应用程序都可以在不进行重大更改的情况下作为C ++进行编译,然后可以使用try ... catch语法。
如果您使用快乐路径设计模式(即,针对嵌入式设备)编写代码,则可以使用运算符“ 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;
}
它实际上不是异常处理程序,但是它为您提供了一种在功能退出时处理错误的方法。
PS:应仅在相同或更深的范围内谨慎使用goto,切勿跳转变量声明。