¿Cuándo usar una matriz de longitud variable en C, pero cuándo una asignación dinámica?

Descubrí la matriz de longitud variable en C99, pero parece que se comporta casi igual que malloc + free.

Las diferencias prácticas que encontré:

Manejo de matriz demasiado grande:

unsigned size = 4000000000;
int* ptr = malloc(size); // ptr is 0, program doesn't crash
int array[size]; // segmentation fault, program crashes

Pérdidas de memoria: solo es posible en la asignación de matriz dinámica:

int* ptr = malloc(size);
...
if(...)
    return;
...
free(ptr);

Vida del objeto y posibilidad de regresar de la función: la matriz asignada dinámicamente vive hasta que la memoria se libera y se puede devolver de la función que asignó la memoria.

Cambio de tamaño: el cambio de tamaño solo es posible con punteros a la memoria asignada.

Mis preguntas son:

¿Cuáles son más diferencias (estoy interesado en consejos prácticos)?¿Cuáles son más problemas que un programador puede tener con ambas formas de matrices con longitud variable?¿Cuándo elegir VLA pero cuándo la asignación de matriz dinámica?¿Qué es más rápido: VLA o malloc + gratis?

Respuestas a la pregunta(2)

Su respuesta a la pregunta