Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/visual-studio-2012/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
如何确保malloc/free fopen/fclose匹配?_C_Fopen - Fatal编程技术网

如何确保malloc/free fopen/fclose匹配?

如何确保malloc/free fopen/fclose匹配?,c,fopen,C,Fopen,我认为以下代码是正常的(malloc/free也是类似的): 它可以为我们打开和关闭文件。使用break通常有助于: int foo() { FILE *fp = fopen("test.in", "r"); int i, result; result = 0; for(i = 0; i < NUM; i ++){ if(Match(fp, i)){ result = i; break

我认为以下代码是正常的(malloc/free也是类似的):


它可以为我们打开和关闭文件。

使用
break
通常有助于:

int foo() {

   FILE *fp = fopen("test.in", "r");

   int i, result;   

   result = 0;
   for(i = 0; i < NUM; i ++){
       if(Match(fp, i)){    
            result = i;
            break;
       }
   }

   fclose(fp);
   return result;
}
intfoo(){
文件*fp=fopen(“test.in”,“r”);
int i,结果;
结果=0;
对于(i=0;i
在linux内核的源代码中,有许多函数必须在返回时处理锁和其他资源。他们通常会在函数的末尾添加一个清理标签,并且每当出现提前返回时,
goto
。我个人建议使用此用法以避免重复代码,也许这是唯一明智的使用
goto

额外的间接层可以确保您不会错过退出函数的机会:

int foo(FILE *fp)
{

   int i;   

   for(i = 0; i < NUM; i ++){
       if(Match(fp, i)){    
            return i;
       }
   }

   return 0;
}

int foo_wrapper(void)
{
    FILE *fp = fopen("test.in", "r");
    int out = foo(fp);
    fclose(fp);
    return out;
}
intfoo(文件*fp)
{
int i;
对于(i=0;i
我将通过goto(在@Charles Peng的回答中提到)扩展异常处理:

你可以这样做:

int func(...)
{
    ...
    f = fopen(...);
    if (f == NULL) {
            log("failed opening blah blah...");
            goto err;
    }
    ...
    m = malloc(...)
    if (m == NULL) {
            log("blah blah...");
            goto err_close_f;
    }
    ...
    if (do_something(...) < 0) {
            log("blah blah...");
            goto err_close_f;
    }
    ...
    r = alloc_resource(...)
    if (r == 0) {
            log("blah blah...");
            goto err_free_m;
    }
    ...
    return 0;


err_free_m:
    free(m);
err_close_f:
    fclose(f);
err:
    return -1;
}
int func(…)
{
...
f=fopen(…);
如果(f==NULL){
日志(“打开失败等等…”);
后悔莫及;
}
...
m=malloc(…)
如果(m==NULL){
日志(“废话…”);
转到错误关闭;
}
...
如果(做某事(…)<0){
日志(“废话…”);
转到错误关闭;
}
...
r=分配资源(…)
如果(r==0){
日志(“废话…”);
去犯错误;
}
...
返回0;
无错误:
自由(m);
错误关闭错误:
fclose(f);
错误:
返回-1;
}

这样做的好处是它非常易于维护。使用此习惯用法时,资源获取和发布的外观有些对称。此外,资源释放超出了主要逻辑,避免了最烦人的过度混乱。检查函数的错误处理是否正确(只需检查它是否跳到适当的点,以及之前的标签是否释放了任何获取的资源)是非常简单的。

不在函数末尾的return语句相当于goto语句。尽管看起来有些函数使用多个返回语句更简单,但我在维护各种代码库时的经验是,每个函数只有一个退出点的代码库更容易维护。

这就是实现方法-使用变量存储状态,并相应地指导程序的执行。是的,它是有效的。如果代码有两个循环,它看起来会很难看,因为我应该设置另一个状态来指示内部循环终止(i=0;iIt适用于此代码。如果您不知道
结果的值会怎么样?如果您不能做一个简单的测试,那么是的,您需要添加状态变量或使用goto。我认为当函数非常大时使用
goto
会更好。我认为最好不要使函数非常大。@Bo Persson:inded、 保持函数小于屏幕真的很有帮助。是的,只要给它们起一个有意义的名字,你就会明白了。谢谢。许多文章说,
goto
应该在代码中消失,现在我想
goto
会出现在我的代码中。:)@lisper-是的,使用正确的工具来完成这项工作。我个人一直认为应该有另一种形式的
goto
,它只限于功能范围(比如,
跳过
)。@你的意思是说goto标签和
goto
应该在同一个功能中吗?(注:它已经在c标准中了。)@lisper-是的,总是这样。我不知道标准中有这样的限制,但是-我从来没有在我写的任何东西中使用过
goto
(虽然我在微处理器引导加载程序代码中使用了“长跳转”,但这是实现定义的行为)@lisper-heh,我刚检查过,你说得对!这段时间,我一直不知道这是一个实际的限制。
int foo(FILE *fp)
{

   int i;   

   for(i = 0; i < NUM; i ++){
       if(Match(fp, i)){    
            return i;
       }
   }

   return 0;
}

int foo_wrapper(void)
{
    FILE *fp = fopen("test.in", "r");
    int out = foo(fp);
    fclose(fp);
    return out;
}
int func(...)
{
    ...
    f = fopen(...);
    if (f == NULL) {
            log("failed opening blah blah...");
            goto err;
    }
    ...
    m = malloc(...)
    if (m == NULL) {
            log("blah blah...");
            goto err_close_f;
    }
    ...
    if (do_something(...) < 0) {
            log("blah blah...");
            goto err_close_f;
    }
    ...
    r = alloc_resource(...)
    if (r == 0) {
            log("blah blah...");
            goto err_free_m;
    }
    ...
    return 0;


err_free_m:
    free(m);
err_close_f:
    fclose(f);
err:
    return -1;
}