C:堆栈内存,转到和"跳转到具有可变修改类型的标识符范围",

Vin*_*nce 22 c memory-management goto

我发现这拒绝编译:

int test_alloc_stack(int size){
    if(0) goto error; // same issue whatever conditional is used
    int apply[size];
    give_values(apply,size);
    return 1;
    error:
        return 0;
}
Run Code Online (Sandbox Code Playgroud)

我得到的错误是:"跳转到具有可变修改类型的标识符范围".使用"goto"消除行并跳转到错误可以解决问题.

如果我使用动态分配申请,那么问题也会消失.编译好:

 int test_alloc_heap(int size){
    if(0) goto error;
    int * apply = calloc(sizeof(int),size);
    give_values(apply,size);
    free(apply);
    return 1;
    error : return 0;
}
Run Code Online (Sandbox Code Playgroud)

到底是怎么回事 ?

Mic*_*urr 24

声明:

int apply[size];
Run Code Online (Sandbox Code Playgroud)

创建一个可变长度数组.当它超出范围时,编译器必须生成一些代码来清除该数组的分配.我想是跳过这样一个对象的范围是禁止的,因为有些实现可能需要安排一些清理代码需要的初始化,如果你跳入范围,初始化将被绕过.

如果更改为动态分配,初始化和清理将成为您的责任,而不是编译器.


use*_*016 19

标准是禁止的:

C99标准,第6.8.6.1段

约束

[...] goto语句不得从具有可变修改类型的标识符范围之外跳转到该标识符的范围内.

这正是你goto正在做的事情,即从范围外跳到apply它内部.

您可以使用以下解决方法来限制以下范围apply:

if(0) goto error;

{
    int apply[size];
    give_values(apply,size);
    return 1;
}

error:
return 0;
Run Code Online (Sandbox Code Playgroud)


Kla*_*äck 7

goto让你跳过分配的行apply(在运行时).

您可以通过以下四种方式之一解决问题:

1:重写您的代码,以免您使用goto.

2:将声明apply移到之前goto.

3:更改范围,使其error:超出以下范围apply:

int test_alloc_stack(int size){
    if(0) goto error; // same issue whatever conditional is used
    {
        int apply[size];
        give_values(apply,size);
        return 1;
    }
    error:
        return 0;
}
Run Code Online (Sandbox Code Playgroud)

4:更改变量声明,以便在编译时确定其大小.