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

时间:2013-12-18 09:29:37

标签: 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;
}

我得到的错误是:“跳转到具有可变修改类型的标识符范围”。 使用“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;
}

发生了什么事?

3 个答案:

答案 0 :(得分:22)

宣言:

int apply[size];

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

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

答案 1 :(得分: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;

答案 2 :(得分: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;
}

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