我有一些我正在使用的C代码,当代码运行时我发现错误但是关于如何正确执行try / catch的信息很少(如在C#或C ++中)。
例如在C ++中,我只是这样做:
try{
//some stuff
}
catch(...)
{
//handle error
}
但在ANSI C中我有点迷失。我尝试了一些在线搜索,但是我没有看到关于如何实现这一点的足够信息/想想我会问这里以防万一有人能指出我正确的方向。
这是我正在使用的代码(相当简单,递归的方法),并希望用try / catch(或等效的错误处理结构)进行包装。
但是我的主要问题是如何在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 < offset ; i++ )
{
printf("found: %d", i);
}
if( abc != NULL )
abc->release();
int childCount = item->getChildCount();
offset++;
for( int i = 0 ; i < childCount ; i++ )
getInfo( offset, item->getChild(i) );
item->release();
}
答案 0 :(得分:25)
一般来说,你没有。
可以使用setjmp
和longjmp
来构建与try / catch非常相似的东西,尽管在C中没有像析构函数或堆栈展开这样的东西,所以RAII是不可能的。您甚至可以使用所谓的“清理堆栈”(参见例如Symbian / C ++)来近似RAII,尽管它不是非常接近的近似值,并且它需要做很多工作。
指示C中的错误或失败的常用方法是返回指示成功状态的值。呼叫者检查返回值并相应地采取行动。例如,请参阅标准C函数:printf
,read
,open
,了解如何指定函数。
混合使用C和C ++代码时,必须确保C ++异常永远不会到达C代码。在编写将从C调用的C ++函数时,请抓住所有内容。
答案 1 :(得分:17)
C不支持异常处理。
有关此问题的一种方法的信息here。这显示了简单的setjmp/longjmp
方法,但也提供了更为复杂的替代方案,深入讨论。
答案 2 :(得分:4)
有经典的展开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 */
}
/* ... */
}
但两种方法都不完全等效。您必须自己管理所有资源,在找到处理程序之前不会自动回滚,等等......
答案 3 :(得分:4)
我喜欢使用的一种有用的编码风格如下。我不知道它是否有一个特定的名称,但当我将一些汇编代码反向工程到等效的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;
}
答案 4 :(得分:4)
这是我在C:exceptions4c中实现的异常处理系统。
它由宏构建,构建在setjmp
和longjmp
之上,并且它是100%可移植的ANSI C.
There您还可以找到我所知道的所有不同实现的列表。
答案 5 :(得分:2)
您可以在本书中找到longjmp的可能实现:C Interfaces and Implementations: Techniques for Creating Reusable Software - David Hanson
答案 6 :(得分:1)
如果您想进行多级跳转,请查看setjmp()
和longjmp()
。它们可以用作原始异常抛出。 setjmp()
函数设置返回位置,并返回状态值。 longjmp()
函数转到返回位置,并提供状态值。您可以根据状态值在catch
之后调用来创建setjmp()
函数。
不管出于何种原因,不要在C ++中使用它们。它们不会进行堆栈展开或调用析构函数。
答案 7 :(得分:0)
由于C ++最初是作为C预处理器实现的,它有Try / Catch,你可以重做Bjarne Stroustrup的工作并编写一个预处理器来完成它。