在调试崩溃时,我在一些代码中遇到了这个问题:
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;
}
Run Code Online (Sandbox Code Playgroud)
第一个malloc失败时会出现问题.因为我们跳过初始化p2
,它包含随机数据和调用可能free(p2)
会崩溃.
我希望/希望这将与C++中的方式相同,其中编译器不允许goto跳过初始化.
我的问题:是跳过标准允许的初始化还是这是gcc实现c99的错误?
flo*_*rin 17
当你通过使用跳过变量定义时,你可以要求gcc警告你-Wjump-misses-init
,然后你可以使用-Werror
(或更确切地说-Werror=jump-misses-init
)强制用户处理它.此警告包含在内,-Wc++-compat
因此gcc开发人员知道代码在C与C++中的行为不同.
您也可以稍微更改代码:
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;
}
Run Code Online (Sandbox Code Playgroud)
...并且只保持标签与初始化变量的配对.使用单元化变量调用许多其他函数时会遇到同样的问题,free恰好是一个更明显的函数.
这样的跳跃确实是标准允许的,所以这不是GCC中的错误.该标准将此情况列为附件I中的建议警告.
在范围方面对C99跳转的唯一限制是跳入变量修改类型变量的范围是非法的,如VLA
int main() {
int n = 5;
goto label; // <- ERROR: illegal jump
int a[n];
label:;
}
Run Code Online (Sandbox Code Playgroud)
换句话说,说"跳跃只是C中的跳跃"是不正确的.在进入变量范围时,跳转受到一些限制,尽管不像C++那样严格.您描述的情况不是受限制的情况之一.
嗯,并不是因为新标准允许在任何地方声明变量,所以使用它总是一个好主意。对于你的情况,我会像我们在经典 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;
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
3241 次 |
最近记录: |