Почему динамически изменяемый массив не может быть выделен в стеке?


В C мы все узнали, что:

int i[500]; // Array of 500 integers on stack
int *i = malloc(sizeof(int) * 500); // Array of 500 integers on heap

Размер стека растет и уменьшается по мере того, как функции выталкивают и выталкивают из него переменные. Но почему массив динамического размера не может быть вытеснен и извлечен из стека?

2 3

2 ответа:

Да, они могут:

Http://gcc.gnu.org/onlinedocs/gcc/Variable-Length.html

Автоматические массивы переменной длины разрешены в стандарте ISO C99, и в качестве расширение GCC принимает их в режиме C90 и в C++. Эти массивы являются объявляется, как и любые другие автоматические массивы, но с длиной, которая равна не постоянное выражение. Хранилище выделяется в точке объявление и освобождение, когда область блока, содержащая декларация выходит. Для Пример:

 FILE *
 concat_fopen (char *s1, char *s2, char *mode)
 {
   char str[strlen (s1) + strlen (s2) + 1];
   strcpy (str, s1);
   strcat (str, s2);
   return fopen (str, mode);
 }

Простой тест:

$ cat testarray.c 
#include <stdio.h>
#include <stdlib.h>

int main(int argc, char** argv) {
  size_t n = atol(argv[1]), i;
  printf("array size: %lu\n", n);

  int a[n];

  for (i=0; i<n; ++i) {
    a[i] = i;
  }

  printf("%d\n", a[0]);

  return 0;
}

$ ./a.out 100000
array size: 100000
0
$ ./a.out 1000000
array size: 1000000
0
$ ./a.out 10000000
array size: 10000000
Segmentation fault
$ ./a.out 100000000
array size: 100000000
Segmentation fault

Если длина массива не изменится с момента первого выделения, то он может быть выделен в стек, даже если его размер не известен на момент компиляции. C99 поддерживает это под именем массивы переменной длины. Предыдущие версии языка могли имитировать то же самое с помощью нестандартной функции alloca.

Однако термин "динамически размерный массив" обычно предполагает, что массив может расти позже снова и снова, до тех пор, пока не останется доступной памяти, и такая вещь на самом деле это невозможно в стеке, потому что пространство стека после массива может быть уже занято другим вызовом функции.