¿Por qué el uso de alloca() no se considera una buena práctica?
alloca()
Asigna memoria en la pila en lugar de en el montón, como en el caso de malloc()
. Entonces, cuando vuelvo de la rutina la memoria se libera. Entonces, en realidad esto resuelve mi problema de liberar memoria asignada dinámicamente. La liberación de la memoria asignada malloc()
es un gran dolor de cabeza y, si de alguna manera se omite, provoca todo tipo de problemas de memoria.
¿ Por qué se desaconseja el uso de alloca()
a pesar de las características anteriores?
La respuesta está ahí en la man
página (al menos en Linux ):
VALOR DEVUELTO La función alloca() devuelve un puntero al comienzo del espacio asignado. Si la asignación provoca un desbordamiento de la pila, el comportamiento del programa no está definido.
Lo que no quiere decir que nunca deba usarse. Uno de los proyectos de OSS en el que trabajo lo usa ampliamente, y siempre y cuando no se abuse de él ( alloca
con valores enormes), está bien. Una vez que superes la marca de "unos pocos cientos de bytes", es hora de usar malloc
y amigos. Es posible que aún obtenga fallas de asignación, pero al menos tendrá alguna indicación de la falla en lugar de simplemente destruir la pila.
Uno de los errores más memorables que tuve tuvo que ver con una función en línea que usaba alloca
. Se manifestó como un desbordamiento de la pila (porque se asigna en la pila) en puntos aleatorios de ejecución del programa.
En el archivo de encabezado:
void DoSomething() {
wchar_t* pStr = alloca(100);
//......
}
En el archivo de implementación:
void Process() {
for (i = 0; i < 1000000; i++) {
DoSomething();
}
}
Entonces, lo que sucedió fue que la función incorporada del compilador (Microsoft VC++ 6) DoSomething
y todas las asignaciones de la pila ocurrían dentro de Process()
la función y, por lo tanto, explotaban la pila. En mi defensa (y no fui yo quien encontró el problema; tuve que ir a llorarle a uno de los desarrolladores senior cuando no pude solucionarlo), no fue sencillo alloca
, fue una conversión de cadenas ATL. macros.
Entonces, la lección es: no lo use alloca
en funciones que crea que podrían estar integradas.
Antigua pregunta, pero nadie mencionó que debería reemplazarse por matrices de longitud variable.
char arr[size];
en lugar de
char *arr=alloca(size);
Está en el estándar C99 y existía como extensión del compilador en muchos compiladores.