ANSI C相当于try / catch?

我有一些我正在使用的C代码,我在代码运行时发现错误,但是关于如何正确执行try / catch(如C#或C ++)的信息很少。

例如在C ++中,我只是这样做:

try{ //some stuff } catch(...) { //handle error } 

但在ANSI C中,我有点迷失。 我尝试了一些在线搜索,但是我没有看到关于如何实现这一点的足够信息/想象我会问这里以防万一有人能指出我正确的方向。

这是我正在使用的代码(相当简单,递归的方法),并希望用try / catch(或等效的error handling结构)进行包装。

但是我的主要问题是如何在ANSI C中执行try / catch …实现/示例不必是递归的。

 void getInfo( int offset, myfile::MyItem * item ) { ll::String myOtherInfo = item->getOtherInfo(); if( myOtherInfo.isNull() ) myOtherInfo = ""; ll::String getOne = ""; myfile::Abc * abc = item->getOrig(); if( abc != NULL ) { getOne = abc->getOne(); } for( int i = 0 ; i release(); int childCount = item->getChildCount(); offset++; for( int i = 0 ; i getChild(i) ); item->release(); } 

一般来说,你没有。

可以使用setjmplongjmp来构建与try / catch非常相似的东西,尽管在C中没有像析构函数或堆栈展开这样的东西,所以RAII是不可能的。 您甚至可以使用所谓的“清理堆栈”(例如,参见Symbian / C ++)来近似RAII,尽管它不是非常接近的近似值,并且它需要做很多工作。

在C中指示错误或失败的常用方法是返回指示成功状态的值。 呼叫者检查返回值并相应地采取行动。 例如,参见标准C函数: printfreadopen ,了解如何指定函数的想法。

混合使用C和C ++代码时,必须确保C ++exception永远不会达到C代码。 在编写将从C调用的C ++函数时,捕获所有内容。

C不支持exception处理。

这里有关于这个问题的一种方法的信息。 这显示了简单的setjmp/longjmp方法,但也提供了更为复杂的替代方案,深入介绍。

有经典的展开goto模式:

 FILE *if = fopen(...); FILE *of = NULL; if (if == NULL) return; of = fopen(...); if (of == NULL) goto close_if; /* ...code... */ if (something_is_wrong) goto close_of; /* ... other code... */ close_of: fclose(of); close_if: fclose(if); return state; 

或者,您可以通过隔离另一个函数中的“try”代码以有限的方式伪造它

 int try_code(type *var_we_must_write, othertype var_we_only_read /*, ... */){ /* ...code... */ if (!some_condition) return 1; /* ...code... */ if (!another_condition) return 2; /* ...code... */ if (last_way_to_fail) return 4; return 0; } void calling_routine(){ /* ... */ if (try_code(&x,y/*, other state */) ) { /* do your finally here */ } /* ... */ } 

但这两种方法都不完全等同。 您必须自己管理所有资源,在找到处理程序之前不会自动回滚,依此类推……

我喜欢使用的一种有用的编码风格如下。 我不知道它是否有一个特定的名称,但是当我将一些汇编代码反向工程为等效的C代码时,我遇到了它。 你确实失去了缩进级别,但这对我来说并不是什么大问题。 留意将指出无限循环的评论者! 🙂

 int SomeFunction() { int err = SUCCESS; do { err = DoSomethingThatMayFail(); if (err != SUCCESS) { printf("DoSomethingThatMayFail() failed with %d", err); break; } err = DoSomethingElse(); if (err != SUCCESS) { printf("DoSomethingElse() failed with %d", err); break; } // ... call as many functions as needed. // If execution gets there everything succeeded! return SUCCESS; while (false); // Something went wrong! // Close handles or free memory that may have been allocated successfully. return err; } 

这是我在C: exceptions4c中实现的exception处理系统。

它由宏构建,构建在setjmplongjmp之上,它是100%可移植的ANSI C.

在那里,您还可以找到我所知道的所有不同实现的列表。

您可以在本书中找到longjmp的可能实现: C接口和实现:创建可重用软件的技术 – David Hanson

你可以在这里和这里找到代码作为本书中使用的样式的一个例子。

如果要进行多级跳转,请查找setjmp()longjmp() 。 它们可以用作原始exception抛出。 setjmp()函数设置一个返回位置,并返回一个状态值。 longjmp()函数转到返回位置,并提供状态值。 您可以通过在setjmp()之后调用来创建catch函数,具体取决于状态值。

不管出于什么原因,不要在C ++中使用它们。 他们不进行堆栈展开或调用析构函数。

由于C ++最初是作为C预处理器实现的,它有Try / Catch,你可以重做Bjarne Stroustrup的工作并编写预处理器来完成它。