¿Es una mala práctica declarar una matriz a media función?

en un esfuerzo por solo preguntar qué es lo que realmente estoy buscando aquí … Realmente solo me preocupa si se considera una mala práctica o no declarar una matriz como la de abajo, donde el tamaño podría variar. Si es … en general lo haría malloc () en su lugar.

void MyFunction() { int size; //do a bunch of stuff size = 10; //but could have been something else int array[size]; //do more stuff... } 

En general, sí, esta es una mala práctica, aunque los nuevos estándares le permiten usar esta syntax. En mi opinión, debe asignar (en el montón) la memoria que desea usar y liberarla una vez que haya terminado con ella. Ya que no hay una forma portátil de verificar si la stack es suficiente para mantener esa matriz, debe usar algunos métodos que realmente se puedan verificar, como malloc / calloc y gratis. En el mundo incrustado, el tamaño de la stack puede ser un problema.

Si le preocupa la fragmentación, puede crear su propio asignador de memoria, pero esta es una historia totalmente diferente.

Eso depende. El primero claramente no es lo que yo llamaría “apropiado”, y el segundo es solo en circunstancias bastante limitadas.

En el primero, no debe emitir el retorno de malloc en C, ya que puede ocultar el error de omitir accidentalmente la inclusión del encabezado correcto ( ).

En el segundo, estás restringiendo el código a C99 o una extensión gcc. Siempre y cuando sea consciente de eso, y funcione para sus propósitos, está bien, pero casi no lo llamaría un ideal de portabilidad.

En cuanto a lo que realmente estás preguntando: con el error menor mencionado anteriormente, el primero es portátil, pero puede ser más lento de lo que te gustaría. Si el segundo es lo suficientemente portátil para sus propósitos, normalmente será más rápido.

Para su pregunta, creo que cada uno tiene sus ventajas y desventajas.

Asignación dinámica:
Lento, pero puede detectar cuando no hay memoria para el progtwigdor marcando el puntero.

Asignación de stack:
Solo en C99 y es increíblemente rápido, pero en caso de desbordamiento de stack, se pierde la suerte.

En resumen, cuando necesite una pequeña matriz, guárdela en la stack. De lo contrario, utilice la memoria dinámica con prudencia.

El argumento en contra de los VLA se ejecuta debido a la absoluta maldad de desbordar la stack, en el momento en que hayas pensado / comprobado lo suficiente para hacerlos seguros, has pensado / comprobado lo suficiente como para usar una matriz de tamaño fijo:

1) Para poder usar VLA de forma segura, debe saber que hay suficiente stack disponible.

2) En la gran mayoría de los casos, la forma en que sabe que hay suficiente stack es que conoce un límite superior en el size requerido, y sabe (o al menos está dispuesto a adivinar o requiere) un límite inferior en la stack disponible , y el uno es más pequeño que el otro. Así que solo usa una matriz de tamaño fijo.

3) En la gran mayoría de los pocos casos que no son tan simples, está utilizando varios VLA (tal vez uno en cada llamada a una función recursiva), y conoce un límite superior en su tamaño total , que es menor que un límite inferior en la stack disponible. Por lo tanto, podría usar una matriz de tamaño fijo y dividirla en partes según sea necesario.

4) Si alguna vez se encuentra con uno de los casos restantes, en una situación en la que el rendimiento de malloc es inaceptable, hágamelo saber …

Puede ser más conveniente, desde el punto de vista del código fuente, usar VLA. Por ejemplo, puede usar sizeof (en el ámbito de definición) en lugar de mantener el tamaño en una variable, y ese negocio con la división de una matriz en trozos puede requerir pasar un parámetro adicional. Así que a veces hay una pequeña ganancia en conveniencia.

También es más fácil pasar por alto el hecho de que está utilizando una gran cantidad de stack, lo que produce un comportamiento indefinido, si en lugar de un int buf[1920*1024] bastante int buf[1920*1024] o int buf[MAX_IMG_SIZE] tiene un int buf[img->size] . Eso funciona bien hasta la primera vez que manejas una imagen grande. Eso es, en términos generales, un problema de pruebas adecuadas, pero si omite algunos posibles insumos difíciles, entonces no será la primera o la última serie de pruebas en hacerlo. Me parece que una matriz de tamaño fijo me recuerda si debo realizar verificaciones de tamaño fijo de la entrada, o reemplazarla con una asignación dinámica y dejar de preocuparme por si encaja en la stack o no. No hay una opción válida para ponerlo en la stack y no te preocupes si se ajusta …

dos puntos desde una perspectiva UNIX / C –

malloc solo es lento cuando lo obligas a llamar a brk (). El significado para matrices razonables es lo mismo que asignar espacio de stack para una variable. Por cierto, cuando usas el método # 2 (a través de alloca y en el código libc que he visto) también invoca brk () para objetos enormes. Así que es un lavado. Nota: con # 2 y # 1 todavía tiene que invocar directa o indirectamente una llamada de tipo memset para poner a cero los bytes en la matriz. Esto es solo una nota al problema real (IMO):

El problema real es la pérdida de memoria. alloca se limpia después de sí misma cuando se vuelve a ejecutar la función, por lo que es menos probable que el # 2 cause un problema. Con malloc / calloc tienes que llamar gratis () o iniciar una fuga.