¿Cuál es la diferencia entre un VLA y la asignación de memoria dinámica a través de malloc?

Tenía curiosidad con esto:

Cuál es la diferencia entre:

const int MAX_BUF = 1000; char* Buffer = malloc(MAX_BUF); 

y:

 char Buffer[MAX_BUF]; 

 char* Buffer = malloc(MAX_BUF); 

crea un puntero char Buffer , asigna dinámicamente MAX_BUF bytes de memoria a través del malloc y hace que Buffer apunte al inicio del espacio asignado. Esta memoria se asigna en el montón.

 char Buffer[MAX_BUF]; 

crea una matriz Buffer de tamaño MAX_BUF que puede contener un máximo de MAX_BUF caracteres. Tenga en cuenta que está creando una matriz de longitud variable (una característica introducida en C99 ) ya que MAX_BUF es una variable. Esta matriz se puede crear en la stack.

Añadiré un poco de información en términos de gestión de memoria, además de lo que otros dijeron.

1) La principal diferencia está aquí:

 const int MAX_BUF = 1000; char* Buffer = malloc(MAX_BUF); 

Debe administrar la memoria asignada manualmente, por ejemplo, el Buffer libre cuando haya terminado de usarlo. Olvidarse de free (o liberarlo dos veces) puede ocasionar problemas.

2) Con el segundo caso:

 char Buffer[MAX_BUF]; 

No necesitas liberar nada. Se destruirá automáticamente. Por lo tanto, evita la tarea de manejar la memoria, lo cual es bueno. Debe intentar evaluar siempre qué enfoque necesita.

Algunos puntos.

  • Dado que el segundo se asigna en la stack, el primer enfoque se toma también cuando se necesita crear un conjunto grande, ya que normalmente hay más memoria disponible en el montón.
  • Además, si crea una matriz con un segundo método, por ejemplo, en el método, el tiempo de vida del objeto será ese método; no podrá usar esa matriz fuera de ese método. Mientras que con la asignación dinámica no es el caso.
  • Caso 1: En

      char Buffer[MAX_BUF]; 

    Buffer es una matriz de tamaño MAX_BUF . La técnica de asignación se llama VLA .

  • Caso 2: En

     const int MAX_BUF = 1000; char* Buffer = malloc(MAX_BUF); 

    Buffer es un puntero al que se le asigna una memoria de tamaño MAX_BUF que es 1000 .

y, una matriz no es lo mismo que un puntero, y C-FAQ tiene una colección Muy buena que detalla los motivos .

La principal diferencia, en términos de usabilidad y comportamiento son:

  1. (1) está en la stack, generalmente Nota , mientras que (2) está en el montón, siempre.
  2. (1) tiene tamaño fijo una vez asignado, (2) puede cambiar de tamaño.
  3. (1) se asigna cuando se llama a la función envolvente y tiene el scope de bloque OTOH, (2) memoria asignada dinámicamente, en tiempo de ejecución y la memoria devuelta tiene un tiempo de vida que se extiende desde la asignación hasta la desasignación.
  4. (1) la memoria asignada no necesita ser administrada por el progtwigdor, mientras que en (2) toda la memoria malloc() d debe estar free() d. [ Cortesía: Giorgi ]

Nota: Wiki

Por ejemplo, el comstackdor GNU C asigna memoria para los VLA en la stack.

La diferencia más notable es el scope. La matriz VLA solo será válida dentro del scope donde se declara, mientras que una matriz dinámica estará disponible en todas partes del progtwig hasta que llame a free() .

En la práctica, los VLA pueden ser más rápidos que la memoria dinámica, en caso de que el comstackdor utilice la asignación de stack para el VLA. Sin embargo, no está especificado por el estándar C donde se asigna un VLA.

(Un comstackdor podría, en teoría, asignar un VLA en el montón, pero luego el comstackdor también sería responsable de la limpieza. No creo que exista ninguna solución de este tipo. Cada comstackdor que he utilizado siempre declara los VLA en la stack. )

Esto significa que los VLA no son aptos para contener grandes cantidades de datos: correría el riesgo de que se desborde la stack. Sin embargo, esto no es una preocupación cuando está usando memoria dinámica.

Los VLA no tienen la misma portabilidad que las matrices dinámicas, ya que los comstackdores terriblemente antiguos no son compatibles con los VLA. En teoría, los nuevos comstackdores de C11 tampoco tienen que soportar los VLA, aunque en este punto no tengo conocimiento de que ningún comstackdor haya sido lo suficientemente estúpido como para abandonar ese soporte.


Comparación / resumen:

  • Los VLA se deben usar cuando hay pequeñas cantidades de datos locales, porque tienen un tiempo de asignación rápido y una limpieza automática.
  • Las matrices dinámicas se deben usar cuando hay grandes cantidades de datos para evitar el desbordamiento de la stack.
  • Las matrices dinámicas se deben usar cuando los datos deben persistir después de la ejecución de una función y deben estar disponibles en otro lugar del progtwig.
  • Los arreglos dynamics se deben usar cuando tiene requisitos de portabilidad excepcionales y / o irracionales.