大 VLA 溢出

Large VLA overflow

基于另一个线程中某人的评论:

VLAs introduce more problems than they solve, because you never know if the declaration is going to crash for x being too large for the stack.

此代码将溢出,因为 sizeof(a) 对于堆栈来说太长了:

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int n = 100000000;
    int a[4][n];

    printf("%zu\n", sizeof(a));

    return 0;
}

但是这个不行,因为sizeof(a)是8(我电脑里指针的大小):

#include <stdio.h>
#include <stdlib.h>

int main(void)
{
    int n = 100000000;
    int (*a)[n];

    printf("%zu\n", sizeof(a));
    a = malloc(sizeof(*a) * 4);
    free(a);
    return 0;
}

我的假设正确吗?

我们能否根据 sizeof 对象来确定使用 VLA 是否危险(可能溢出)?

int (*a)[n]; 不是 VLA,而是指向 VLA 的指针。所以 OP 2 的例子不是一个足够接近的比较。


正如 评论的那样,防止堆栈溢出是任何自动分配的问题。递归会过度消耗堆栈。局部大变量也会过度消耗堆栈。

VLA 只是最有可能被滥用的一种。

// Qualified use of VLA
int len = snprintf(NULL, 0 "%d", some_int);
assert(len > 0);
char vla_good[len+1];
len = snprintf(vla_good, len+1, "%d", some_int);

// Unqualified
int x;
scanf("%d", &x);
char vla_bad[x];  // who knowns what x may be, did scanf() even work?

VLAs introduce more problems than they solve, because you never know if the declaration is going to crash for x being too large for the stack.

Can we determine if the use of a VLA is dangerous?

使用正确的工具完成任务。 通常 worst-case 小的 fixed-sized 数组就可以了。 VLA 的用途有限。在声明 VLA 之前,健壮的代码将确保数组元素计数不是愚蠢的。

请注意,VLA 可用,因为 C11 可选择支持 C99。

VLA 还不错,他们是 just drawn that way