C++ ANSI C等效于try/catch?
我有一些正在使用的C代码,在代码运行时我会发现错误,但对于如何进行正确的尝试/捕获(如在C#或C++中)几乎没有什么信息C++ ANSI C等效于try/catch?,c++,c,exception-handling,try-catch,ansi-c,C++,C,Exception Handling,Try Catch,Ansi C,我有一些正在使用的C代码,在代码运行时我会发现错误,但对于如何进行正确的尝试/捕获(如在C#或C++中)几乎没有什么信息 例如C++中,我只做: try{ //some stuff } catch(...) { //handle error } 但在ANSI C中,我有点迷路了。我尝试了一些在线搜索,但是我没有看到足够的关于如何实现的信息/我想我会在这里询问,以防有人能给我指出正确的方向 下面是我正在使用的代码(相当简单的递归方法),并希望使用try/catch(或等效的错误处理结构)进行包装
例如C++中,我只做:
try{
//some stuff
}
catch(...)
{
//handle error
}
但在ANSI C中,我有点迷路了。我尝试了一些在线搜索,但是我没有看到足够的关于如何实现的信息/我想我会在这里询问,以防有人能给我指出正确的方向
下面是我正在使用的代码(相当简单的递归方法),并希望使用try/catch(或等效的错误处理结构)进行包装
然而,我的主要问题只是如何在ANSIC中进行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();
}
void getInfo(整数偏移量,myfile::MyItem*item)
{
ll::String myOtherInfo=item->getOtherInfo();
if(myOtherInfo.isNull())
myOtherInfo=“”;
ll::String getOne=“”;
myfile::Abc*Abc=item->getOrig();
如果(abc!=NULL)
{
getOne=abc->getOne();
}
对于(int i=0;irelease();
int childCount=item->getChildCount();
offset++;
for(int i=0;i获取子项(i));
项目->发布();
}
一般来说,你不需要
可以使用setjmp
和longjmp
来构建类似于try/catch的东西,尽管C中没有析构函数或堆栈展开之类的东西,所以RAII是不可能的。您甚至可以使用所谓的“清理堆栈”(例如,请参见Symbian/C++)来近似RAII,尽管这不是一个非常接近的近似值,而且需要大量的工作
在C中指示错误或失败的通常方法是返回一个指示成功状态的值。调用者检查返回值并相应地采取行动。例如,参见标准C函数:printf
、read
、open
,了解如何指定函数
<>当混合C和C++代码时,必须确保C++异常永远不会达到C代码。当编写C++函数时,将从C调用,捕捉所有。 如果要进行多级别跳转,请查阅<代码> SETJMP()/<代码>和<代码> LojJMP()/<代码>。它们可以用作基本异常抛出。
setjmp()
函数设置返回位置,并返回状态值。longjmp()
函数转到返回位置,并提供状态值。根据状态值,您可以在setjmp()
之后调用函数来创建catch
函数
无论如何,不要在C++中使用它们。它们不进行堆栈展开或调用析构函数。C不支持异常处理
有一种解决这个问题的方法。这显示了简单的
setjmp/longjmp
方法,但也提供了更复杂的替代方案,由于C++最初是作为C预处理器实现的,所以它可以尝试重做Bjarne Stroustrup的工作并编写一个预处理器来完成它。 < P>有经典的解卷<代码> Goto S模式:
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 */
}
/* ... */
}
但这两种方法都不完全相同。您必须自己管理所有资源,在找到处理程序之前不会自动回滚,等等……您可以在本书中找到使用longjmp的可能实现: 您可以找到代码,作为本书中使用的样式示例: 除了
/* $Id$ */
#ifndef EXCEPT_INCLUDED
#define EXCEPT_INCLUDED
#include <setjmp.h>
#define T Except_T
typedef struct T {
const char *reason;
} T;
typedef struct Except_Frame Except_Frame;
struct Except_Frame {
Except_Frame *prev;
jmp_buf env;
const char *file;
int line;
const T *exception;
};
enum { Except_entered=0, Except_raised,
Except_handled, Except_finalized };
extern Except_Frame *Except_stack;
extern const Except_T Assert_Failed;
void Except_raise(const T *e, const char *file,int line);
#ifdef WIN32
#include <windows.h>
extern int Except_index;
extern void Except_init(void);
extern void Except_push(Except_Frame *fp);
extern void Except_pop(void);
#endif
#ifdef WIN32
/* $Id$ */
#define RAISE(e) Except_raise(&(e), __FILE__, __LINE__)
#define RERAISE Except_raise(Except_frame.exception, \
Except_frame.file, Except_frame.line)
#define RETURN switch (Except_pop(),0) default: return
#define TRY do { \
volatile int Except_flag; \
Except_Frame Except_frame; \
if (Except_index == -1) \
Except_init(); \
Except_push(&Except_frame); \
Except_flag = setjmp(Except_frame.env); \
if (Except_flag == Except_entered) {
#define EXCEPT(e) \
if (Except_flag == Except_entered) Except_pop(); \
} else if (Except_frame.exception == &(e)) { \
Except_flag = Except_handled;
#define ELSE \
if (Except_flag == Except_entered) Except_pop(); \
} else { \
Except_flag = Except_handled;
#define FINALLY \
if (Except_flag == Except_entered) Except_pop(); \
} { \
if (Except_flag == Except_entered) \
Except_flag = Except_finalized;
#define END_TRY \
if (Except_flag == Except_entered) Except_pop(); \
} if (Except_flag == Except_raised) RERAISE; \
} while (0)
#else
#define RAISE(e) Except_raise(&(e), __FILE__, __LINE__)
#define RERAISE Except_raise(Except_frame.exception, \
Except_frame.file, Except_frame.line)
#define RETURN switch (Except_stack = Except_stack->prev,0) default: return
#define TRY do { \
volatile int Except_flag; \
Except_Frame Except_frame; \
Except_frame.prev = Except_stack; \
Except_stack = &Except_frame; \
Except_flag = setjmp(Except_frame.env); \
if (Except_flag == Except_entered) {
#define EXCEPT(e) \
if (Except_flag == Except_entered) Except_stack = Except_stack->prev; \
} else if (Except_frame.exception == &(e)) { \
Except_flag = Except_handled;
#define ELSE \
if (Except_flag == Except_entered) Except_stack = Except_stack->prev; \
} else { \
Except_flag = Except_handled;
#define FINALLY \
if (Except_flag == Except_entered) Except_stack = Except_stack->prev; \
} { \
if (Except_flag == Except_entered) \
Except_flag = Except_finalized;
#define END_TRY \
if (Except_flag == Except_entered) Except_stack = Except_stack->prev; \
} if (Except_flag == Except_raised) RERAISE; \
} while (0)
#endif
#undef T
#endif
/*$Id$*/
#ifndef,不包括
#定义所包含的内容
#包括
#定义T,除了
类型定义结构T{
常量字符*原因;
}T;
typedef struct Except_Frame Except_Frame;
除框架外的结构{
除了_Frame*prev;
jmp_buf env;
常量字符*文件;
内线;
常数T*例外;
};
枚举{Except_entered=0,Except_raised,
除(已处理)外,除(已完成)外;;
extern Except_Frame*Except_stack;
外部常量,但断言失败;
无效,但上升除外(常量T*e、常量字符*文件、int行);
#ifdef WIN32
#包括
除索引外的外部int;
外部无效,但初始(无效)除外;
外部无效,推送除外(框架*fp除外);
外部无效,但_pop(无效)除外;
#恩迪夫
#ifdef WIN32
/*$Id$*/
#定义提升(e),但不包括提升(&(e),uuuu文件uuu,uuu行uu)
#定义除提升外的重新提升(除帧异常、\
除了_frame.file,除了_frame.line)
#定义返回开关(除_pop(),0外)默认值:返回
#定义TRY do{\
除_标志外的易失性int\
除_帧外除_帧\
如果(除_索引==-1外)\
除了_init()\
除了推送(除了框架)\
Except_flag=setjmp(Except_frame.env)\
如果(除\u标志==除输入的\u){
#定义(e)除外\
如果(除_标志==除输入的_外)除_弹出()\
}else如果(除了_frame.exception==&(e)){\
Except_标志=Except_已处理;
#定义其他\
如果(除_标志==除输入的_外)除_弹出()\
}否则{\
Except_标志=Except_已处理;
#最后确定\
如果(除_标志==除输入的_外)除_弹出()\
} { \
如果(除\u标志==除输入的\u)\
Except_标志=Except_最终确定;
#定义结束时间\
如果(除_标志==除输入的_外)除_弹出()\
}如果(除_标志==除_升起)重新升起\
}而(0)
#否则
#定义提升(e),但不包括提升(&(e),uuuu文件uuu,uuu行uu)
#定义除提升外的重新提升(除帧异常、\
除了_frame.file,除了_frame.line)
#定义返回开关(除\u堆栈=除\u堆栈->上一个,0)默认值:返回
#定义TRY do{\
除_标志外的易失性int\
除_帧外除_帧\
Exception_frame.prev=Exception_stack\
Except_stack=&Except_frame\
Except_flag=setjmp(Except_frame.env)\
如果(除\u标志==除输入的\u){
#定义(e)除外\
static char rcsid[] = "$Id$" "\n$Id$";
#include <stdlib.h>
#include <stdio.h>
#include "assert.h"
#include "except.h"
#define T Except_T
Except_Frame *Except_stack = NULL;
void Except_raise(const T *e, const char *file,
int line) {
#ifdef WIN32
Except_Frame *p;
if (Except_index == -1)
Except_init();
p = TlsGetValue(Except_index);
#else
Except_Frame *p = Except_stack;
#endif
assert(e);
if (p == NULL) {
fprintf(stderr, "Uncaught exception");
if (e->reason)
fprintf(stderr, " %s", e->reason);
else
fprintf(stderr, " at 0x%p", e);
if (file && line > 0)
fprintf(stderr, " raised at %s:%d\n", file, line);
fprintf(stderr, "aborting...\n");
fflush(stderr);
abort();
}
p->exception = e;
p->file = file;
p->line = line;
#ifdef WIN32
Except_pop();
#else
Except_stack = Except_stack->prev;
#endif
longjmp(p->env, Except_raised);
}
#ifdef WIN32
_CRTIMP void __cdecl _assert(void *, void *, unsigned);
#undef assert
#define assert(e) ((e) || (_assert(#e, __FILE__, __LINE__), 0))
int Except_index = -1;
void Except_init(void) {
BOOL cond;
Except_index = TlsAlloc();
assert(Except_index != TLS_OUT_OF_INDEXES);
cond = TlsSetValue(Except_index, NULL);
assert(cond == TRUE);
}
void Except_push(Except_Frame *fp) {
BOOL cond;
fp->prev = TlsGetValue(Except_index);
cond = TlsSetValue(Except_index, fp);
assert(cond == TRUE);
}
void Except_pop(void) {
BOOL cond;
Except_Frame *tos = TlsGetValue(Except_index);
cond = TlsSetValue(Except_index, tos->prev);
assert(cond == TRUE);
}
#endif
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;
}