3

Based on a comment of someone in another thread:

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.

This code will overflow because sizeof(a) is too long for the stack:

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

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

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

    return 0;
}

But this one can not because sizeof(a) is 8 (the size of a pointer in my computer):

#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;
}

Is my assumption correct?

Can we determine if the use of a VLA is dangerous or not (may overflow) based on the sizeof the object?

David Ranieri
  • 39,972
  • 7
  • 52
  • 94
  • 3
    `int (*a)[n];` is not a VLA. It is a pointer to a VLA. – chux - Reinstate Monica Feb 08 '17 at 20:57
  • 1
    Why do you multiply `sizeof(*a)` by 4? Are you making an array of 100000000x4? – Sergey Kalinichenko Feb 08 '17 at 20:57
  • 1
    Besides, as chux has noted, `int (*a)[n]` is a pointer to a VLA, not itself a VLA. – Sergey Kalinichenko Feb 08 '17 at 20:58
  • 1
    It's context dependent (context = system + what the calls stack looks like when the VLA is created). It think it's a good idea to only use stack-backed arrays if the size is both fairly small (definitely 100B to 4096 tops) and transient (the frame will be popped soon). On Linux process stacks default to 8MiB I believe so you definitely can't overflow that. – Petr Skocik Feb 08 '17 at 20:59
  • @dasblinkenlight, yes, edited (is just an example) – David Ranieri Feb 08 '17 at 21:00
  • @chux, makes sense! – David Ranieri Feb 08 '17 at 21:00
  • 1
    The general answer is no -- there's no portable way to find if VLAs could fail. The issue of potential allocation failure for VLA is applicable to any "stack" allocation as well (*automatic storage duration*). Not sure how the 2nd segment is related to your question as it simply declares a pointer (to an array). – P.P Feb 08 '17 at 21:01
  • 1
    It seems like you're asking "how do we prevent stack overflow". VLAs are nothing special, the same problem exists for any automatic allocation. (The comment you quote at the start is lame) – M.M Feb 08 '17 at 21:09

1 Answers1

7

int (*a)[n]; is not a VLA, but a pointer to a VLA. So OP 2 examples are not a close enough comparison.


As @M.M commented, preventing stack overflow is a problem with any automatic allocation. Recursion can overly consume a stack. Local large variables can overly consume a stack too.

A VLA is simply one of the more likely to be used egregiously.

// 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?

Use the right tool for the task. Usually a worst-case small fixed-sized arrays will do. VLAs have limited uses. Robust code would insure the array element count is not foolish before declaring a VLA.

Note that VLA, available since C99 is optionally supported in C11.

VLA are not bad, they are just drawn that way.

Community
  • 1
  • 1
chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256