代码之家  ›  专栏  ›  技术社区  ›  R Samuel Klatchko

c99转到过去的初始化

  •  21
  • R Samuel Klatchko  · 技术社区  · 16 年前

    在调试崩溃时,我在一些代码中遇到了这个问题:

    int func()
    {
        char *p1 = malloc(...);
        if (p1 == NULL)
            goto err_exit;
    
        char *p2 = malloc(...);
        if (p2 == NULL)
            goto err_exit;
    
        ...
    
    err_exit:
        free(p2);
        free(p1);
    
        return -1;
    }
    

    p2 ,它包含随机数据和 free(p2) 可能会崩溃。

    我希望/希望这将被处理的方式与C++中的编译器不允许Goto跨越初始化的方式相同。

    我的问题是:跳过标准允许的初始化还是gcc实现c99中的一个bug?

    7 回复  |  直到 16 年前
        1
  •  17
  •   Antonio    9 年前

    当您跳过变量定义时,可以使用 -Wjump-misses-init -Werror (或者更确切地说, -Werror=jump-misses-init -Wc++-compat

    您还可以稍微更改代码:

    int func()
    {
        char *p1 = malloc(...);
        if (p1 == NULL)
            goto err_exit_1;
    
        char *p2 = malloc(...);
        if (p2 == NULL)
            goto err_exit_2;
    
        ...
    
    err_exit_2:
        free(p2);
    err_exit_1:
        free(p1);
    
        return -1;
    }
    

    ... 保持标签和初始化变量的配对。使用单位化变量调用许多其他函数也会遇到同样的问题,free恰好是一个更明显的问题。

        2
  •  9
  •   AnT stands with Russia    16 年前

    标准确实允许这样的跳转,所以这不是GCC中的bug。本标准将此情况列为附录I中的建议警告。

    C99中关于范围的跳转的唯一限制是跳转到可变修改类型的变量(如VLA)的范围是非法的

    int main() {
      int n = 5;
      goto label; // <- ERROR: illegal jump
      int a[n];
    label:;
    }
    

        3
  •  4
  •   Patrick Schlüter    6 年前

    嗯,并不是因为新标准允许在任何地方进行变量声明,所以使用它总是一个好主意。在你的情况下,我会像我们在经典C。

    int func()
    {
    char *p1 = NULL;    /* So we have a defined value */
    char *p2 = NULL;
    
      p1 = malloc(...);
      if(!p1)
        goto err_exit;
    
      p2 = malloc(...);
      if(!p2)
        goto err_exit;
    
      ...
    
      err_exit:
        free(p2);
        free(p1);
    
      return -1;
    }
    
        4
  •  3
  •   Christoph    16 年前

    这不是gcc中的bug。跳就是跳C。没有应用特殊逻辑。问题是您没有初始化指向的指针 NULL free(NULL) 不会崩溃的。启动函数 char *p1 = NULL, *p2 = NULL; 一切都会好起来的。

        5
  •  2
  •   Oleg Razgulyaev    16 年前

    如果我用-O2标志编译代码

    gcc -Wall -std=c99 -O2 jump.c
    

    我得到警告:

    jump.c: In function ‘func’:
    jump.c:10: warning: ‘p2’ may be used uninitialised in this function
    

    没有优化就没有警告

        6
  •  0
  •   Community Mohan Dere    9 年前

    AndreyT says

    int func()
    {
        char *p1 = malloc(...);
        if (p1 == NULL)
            goto err_exit_p1;
    
        char *p2 = malloc(...);
        if (p2 == NULL)
            goto err_exit;
    
        ...
    
    err_exit:
        free(p2);
    err_exit_p1:
        free(p1);
    
        return -1;
    }
    

    这是一个标准模式-“早期错误”导致跳转到错误退出代码的后面部分。

        7
  •  -5
  •   Puppy    16 年前