C++ ANSI C等效于try/catch?

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代码,在代码运行时我会发现错误,但对于如何进行正确的尝试/捕获(如在C#或C++中)几乎没有什么信息

例如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;
}