大VLA溢出

时间:2017-02-08 20:51:53

标签: c stack-overflow variable-length-array

基于另一个帖子中某人的评论:

  

VGA引入的问题多于他们解决的问题,因为您永远不会知道   如果声明要崩溃,因为x太大了   叠加。

此代码将溢出,因为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的使用是否危险(可能会溢出)吗?

1 个答案:

答案 0 :(得分:5)

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

@M.M所述,防止堆栈溢出是任何自动分配的问题。递归可以过度消耗堆栈。本地大变量也可能过度消耗堆栈。

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?
  

VLA引入的问题比他们解决的问题多,因为您永远不知道声明是否会因为x对于堆栈来说太大而崩溃。

     

我们可以确定使用VLA是否危险吗?

使用正确的工具完成任务。通常最坏情况的小型固定大小的阵列都可以。 VLA的用途有限。强大的代码可以确保在声明VLA之前数组元素计数并不愚蠢。

请注意,自C99起可用的VLA在C11中可选。

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