C-为什么我可以进入Alloca:D变量的范围,而不是变量长度数组



请参阅此测试程序:

#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
  if (argc < 2)
    goto end;
  char s[strlen(argv[1]) + 1];
  strcpy(s, argv[1]);
  printf("s=%sn", s);
end:
  return 0;
}

它无法与"跳入具有可变修改类型的标识符范围"的错误编译(请参阅其他问题(。

但是,如果我将s的声明更改为此(并包含alloca.h(,则可以编译罚款:

char *s = alloca(strlen(argv[1]) + 1);

为什么C标准允许跳入使用alloca创建的对象的范围,而不是可变长度数组?我以为它们是等效的。

这是因为编译器必须使用VLAS运行范围框架。换句话说,您告诉它跳到地址:END,但您要求它跳过该范围框架的初始化代码。

初始化VLA空间的代码就在计算VLA长度的表达式之前。如果跳过该代码,某些Goto可以做的,所有程序都将符合。

想象类似:

if (cond) goto end;
...
char a[expr];
end:
a[i] = 20;

在这种情况下,当您跳到vla a的突变器时,代码将简单地示出,但没有初始化。必须插入定义的初始化VLA的代码。

现在关于alloca。编译器将执行相同的操作,但无法检测到segfault。

所以这将使编译器的部分没有警告/错误。

逻辑与VLA相同。

int main(int argc, char *argv[])
{
    goto end;
    char *s = alloca(100);
end:
    s[1] = 2;
    return 0;
}

在ISO 9899中,这就是为什么他们插入语句:

6.8.6.1 goto语句 - 约束

1 goto语句中的标识符应为标签命名 封闭功能中的某个地方。一个声明不会跳 从具有变量修改的标识符范围外 输入该标识符的范围内。

编译器在静态分析期间无法检测到此问题的正确答案,因为这实际上是halting problem

除了该程序在声明后跳跃的问题外, sizeof也有一个问题。

想象一下您的程序已扩展为:

end:
    printf("size of str: %zun", sizeof s);
    return 0;
}

对于alloca版本,sizeof s == sizeof(char*),可以在编译时计算,一切都很好。但是,对于VLA版本,s的长度未知,并且sizeof s 无法计算

相关内容

  • 没有找到相关文章