Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 在循环中释放内存,而不考虑返回代码_C_Loops_Error Handling_Goto - Fatal编程技术网

C 在循环中释放内存,而不考虑返回代码

C 在循环中释放内存,而不考虑返回代码,c,loops,error-handling,goto,C,Loops,Error Handling,Goto,我有以下C伪代码: int main() { int rc = 0; for (int i = 1; i < 10; i++) { char *data = malloc(i); // Each iteration has a different alloc size rc = do_something(data); if (rc != 0) goto cleanup; rc = do_something

我有以下C伪代码:

int main()
{
    int rc = 0;

    for (int i = 1; i < 10; i++) {
        char *data = malloc(i); // Each iteration has a different alloc size

        rc = do_something(data);
        if (rc != 0) goto cleanup;

        rc = do_something_else();
        if (rc != 0) goto cleanup;

cleanup:
        free(data);
        if (rc != 0) break;
    }
    return rc;
}
intmain()
{
int rc=0;
对于(int i=1;i<10;i++){
char*data=malloc(i);//每个迭代都有不同的alloc大小
rc=做某事(数据);
如果(rc!=0)转到清理;
rc=做点别的事();
如果(rc!=0)转到清理;
清理:
免费(数据);
如果(rc!=0)中断;
}
返回rc;
}
我想模拟Python的
try…finally
模式,在调用的函数返回错误时中断循环,但仅在完成一些必要的清理工作之后


到目前为止,代码在我看来还行,但我对C还是新手。是否有一种不同的模式可以避免重复的
rc!=0
免费后测试?(我知道有些人认为<代码> Goto 无条件错误,但我认为它是对这种情况最干净的解决方案。)

< P>从我的经验来看,很少有一个真正简单的解决方法来解决C.

中的错误处理问题。 你可以这样做,但如果这真的更好,这是有争议的

int main()
{
    int rc = 0;

    for (int i = 1; i < 10; i++) {
        char *data = malloc(i); // Each iteration has a different alloc size

        rc = do_something(data);
        if (rc != 0) goto cleanup;

        rc = do_something_else();
        if (rc != 0) goto cleanup;
        
        free(data);
        continue;

cleanup:
        free(data);
        break;
    }
    return rc;
}
intmain()
{
int rc=0;
对于(int i=1;i<10;i++){
char*data=malloc(i);//每个迭代都有不同的alloc大小
rc=做某事(数据);
如果(rc!=0)转到清理;
rc=做点别的事();
如果(rc!=0)转到清理;
免费(数据);
继续;
清理:
免费(数据);
打破
}
返回rc;
}

如果需要资源管理,并且需要执行一组检查,而每次故障都需要停止流并执行所需的清理,则可以使用这种模式(使用
转到

在我看来,要使代码更干净,就要放置
rc!=0
循环的
内的条件:

int rc = 1;
for (int i = 0; i < 10 && rc != 0; i++)
{
    ...

请注意,
释放
一个
NULL
指针是完全合法的。

在您所展示的特定代码/案例中,您可以通过使用函数而不是
malloc
来消除任何类型的每循环清理的需要。这将简单地用一个新的块(大小不同)替换上一个循环(如果有)上分配的内存。然后,您可以简单地将任何清理(即调用
free
)延迟到循环之外

    char *data = NULL;
    for (int i = 1; i < 10; i++) {
        data = malloc(i); // Each iteration has a different alloc size

        rc = do_something(data);
        if (rc != 0) break;

        rc = do_something_else();
        if (rc != 0) break;

        free(data);
        data = NULL;
    }
    if (data) {
        free(data);
    }
无论何时发生错误,您仍然可以使用
break
语句退出循环;或者,如评论中所述,您可以添加一个
rc!=0
测试循环的条件

下面是一些C代码,它将按照我所指出的那样工作(但是,当然,您需要两个名为functions的实际定义才能工作):

#包括
int do_something(字符*数据);
int do_something_other(void);
int main()
{
int rc=0;
char*data=NULL;
对于(大小i=1;i<10;i++){
char*temp=realloc(data,i);//如果“data”为NULL(第1个循环)->与malloc相同
如果(temp==NULL){//分配失败。。。
//错误消息
打破
}
data=temp;//成功分配,因此更新“data”指针
rc=做某事(数据);
如果(rc!=0)中断;
rc=做点别的事();
}
free(data);//我们现在只需要清理一次(允许使用NULL调用)。
返回rc;
}

请随时要求进一步澄清和/或解释。

您可以在循环之外声明变量。然后只要在释放变量时将其设为null,并在循环结束后检查是否存在此问题

    char *data = NULL;
    for (int i = 1; i < 10; i++) {
        data = malloc(i); // Each iteration has a different alloc size

        rc = do_something(data);
        if (rc != 0) break;

        rc = do_something_else();
        if (rc != 0) break;

        free(data);
        data = NULL;
    }
    if (data) {
        free(data);
    }
char*data=NULL;
对于(int i=1;i<10;i++){
data=malloc(i);//每个迭代都有不同的alloc大小
rc=做某事(数据);
如果(rc!=0)中断;
rc=做点别的事();
如果(rc!=0)中断;
免费(数据);
数据=空;
}
如果(数据){
免费(数据);
}

您可以添加
rc!=0
进入
for
循环:
for(int i=0;i<10&&rc!=0;i++)
。。。只需初始化
rc=1而不是0。在这种情况下,您不需要使用
中断
@AlexLop。美好的这比我的答案还要好。这非常吸引人,可能适用于我的真实代码,其中alloc和free调用在一个单独的函数中,但它提出了一个更广泛的问题:在被调用的函数中是否有人担心用realloc替换malloc,哪一个是泛型的,在广泛的上下文中被调用?@user3758232如果你总是有一个
malloc的循环模式。。。免费
,然后将其替换为
realloc
(在循环中)和循环后的单个
免费
,不会改变整体行为模式(只要采取相关预防措施防止调用
realloc
,如我在代码中所示)。@user3758232,如果传递指向使用
realloc
的函数的指针,则必须传递指向指针的指针,才能将修改后的值返回给调用方。但当你使用
malloc
时,情况可能也是如此。我已经接受了一个答案,但这实际上是最通用的答案,因为它适用于不特定于
alloc
/
realloc
的情况,或者我无法修改该代码的情况。