加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

在初始化C中的多个资源的函数中处理错误(清理和中止)的一些好方

发布时间:2020-12-16 09:58:47 所属栏目:百科 来源:网络整理
导读:首先,如果有人可以重新提出问题以使其更清楚,请执行. C编程中常见的情况是要按特定顺序初始化/分配多个资源.每个资源都是后续资源初始化的先决条件.如果其中一个步骤失败,则必须取消分配先前步骤的剩余资源.理想的伪代码(利用神奇的通用pure-unobtainium cle
首先,如果有人可以重新提出问题以使其更清楚,请执行.

C编程中常见的情况是要按特定顺序初始化/分配多个资源.每个资源都是后续资源初始化的先决条件.如果其中一个步骤失败,则必须取消分配先前步骤的剩余资源.理想的伪代码(利用神奇的通用pure-unobtainium clean_up_and_abort()函数)看起来大致如下:

err=alloc_a()
if(err)
    clean_up_and_abort()

err=alloc_b()
if(err)
    clean_up_and_abort()

err=alloc_c()
if(err)
    clean_up_and_abort()

// ...

profit()

我已经看到了几种处理这种方法的方法,所有这些方法似乎都有很大的缺点,至少在人们倾向于考虑“良好实践”方面.

在处理这种情况时,构造代码的最可读和最不容易出错的方法是什么?效率是优选的,但为了便于阅读,可以牺牲合理的效率.请列出优点和缺点.欢迎讨论多种方法的答案.

我们的目标是希望最终得到一套解决这个问题的几种首选方法.

我将从我已经看过的一些方法开始,请对它们进行评论并添加其他方法.

解决方法

4:全局变量,哇哦!因为每个人都喜欢全局变量,就像他们喜欢goto一样.但严重的是,如果将变量的范围限制为文件范围(使用static关键字),那就不是那么糟糕了.附注:清理函数接收/返回错误代码不变,以便在init_function中整理代码.

static A *a = NULL;
static B *b = NULL;
static C *c = NULL;

uint32_t cleanup( uint32_t errcode )
{
    if ( c )
        dealloc_c(&c);
    if ( b )
        dealloc_b(&b);
    if ( a )
        dealloc_a(&a);

    return errcode;
}

uint32_t init_function( void )
{
    if ( alloc_a(&a) != SUCCESS )
        return cleanup(INIT_FAIL_A);

    if ( alloc_b(&b) != SUCCESS )
        return cleanup(INIT_FAIL_B);

    if ( alloc_c(&c) != SUCCESS )
        return cleanup(INIT_FAIL_C);

    profit(a,b,c);
    return INIT_SUCCESS;
}

5:人造OOP.对于那些无法处理真相的人(全局变量在C程序中实际有用),您可以采用C方法. C获取所有全局变量,将它们放入结构中,并将它们称为“成员”变量.不知怎的,这让每个人都开心.

诀窍是将指向结构的指针传递给所有函数,作为第一个参数. C在幕后执行此操作,在C中您必须明确地执行此操作.我调用指针,以避免与此冲突/混淆.

// define a class (uhm,struct) with status,a cleanup method,and other stuff as needed
typedef struct stResources
{
    char *status;
    A *a;
    B *b;
    C *c;
    void (*cleanup)(struct stResources *that);
}
stResources;

// the cleanup method frees all resources,and frees the struct
void cleanup( stResources *that )
{
    if ( that->c )
        dealloc_c( &that->c );
    if ( that->b )
        dealloc_b( &that->b );
    if ( that->a )
        dealloc_a( &that->a );

    free( that );
}

// the init function returns a pointer to the struct,or NULL if the calloc fails
// the status member variable indicates whether initialization succeeded,NULL is success
stResources *init_function( void )
{
    stResources *that = calloc( 1,sizeof(stResources) );

    if ( !that )
        return NULL;

    that->cleanup = cleanup;

    that->status = "Item A is out to lunch";
    if ( alloc_a( &that->a ) != SUCCESS )
        return that;

    that->status = "Item B is never available when you need it";
    if ( alloc_b( &that->b ) != SUCCESS )
        return that;

    that->status = "Item C is being hogged by some other process";
    if ( alloc_c( &that->c ) != SUCCESS )
        return that;

    that->status = NULL;  // NULL is success
    return that;
}

int main( void )
{
    // create the resources
    stResources *resources = init_function();

    // use the resources
    if ( !resources )
        printf( "Buy more memory alreadyn" );
    else if ( resources->status != NULL )
        printf( "Uhm yeah,so here's the deal: %sn",resources->status );
    else
        profit( resources->a,resources->b,resources->c );

    // free the resources
    if ( resources )
        resources->cleanup( resources );
}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读