¿Por qué el uso de alloca() no se considera una buena práctica?


alloca() asigna memoria de Pila en lugar de montón que es el caso en malloc(). Entonces, cuando regreso de la rutina, la memoria se libera. Por lo tanto, en realidad esto resuelve mi problema de liberar de memoria dinámicamente asignado. La liberación de la memoria asignada a través de malloc() es un dolor de cabeza importante y si de alguna manera se pierde conduce a todo tipo de problemas de memoria.

¿Por qué se desaconseja el uso de alloca() a pesar de las características anteriores?

Author: Mohit Kanwar, 2009-06-19

24 answers

La respuesta está justo ahí en la página man (al menos en Linux):

VALOR DEVUELTO La función alloca () devuelve un puntero al principio de la espacio asignado. Si el causas de asignación desbordamiento de pila, el comportamiento del programa no está definido.

Lo que no quiere decir que nunca se debe usar. Uno de los proyectos de OSS en los que trabajo lo usa ampliamente, y mientras no estés abusando de él (alloca'grandes valores), está bien. Una vez que vayas más allá de la marca de "pocos cientos de bytes", es hora de usar malloc y amigos, en su lugar. Todavía puede obtener errores de asignación, pero al menos tendrá alguna indicación de la falla en lugar de simplemente soplar la pila.

 193
Author: Sean Bright,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-01 21:49:26

Uno de los errores más memorables que tuve tenía que ver con una función en línea que utiliza alloca. Se manifestó como un desbordamiento de pila (porque se asigna en la pila) en puntos aleatorios de la ejecución del programa.

En el archivo de cabecera:

void DoSomething() {
   wchar_t* pStr = alloca(100);
   //......
}

En el archivo de implementación:

void Process() {
   for (i = 0; i < 1000000; i++) {
     DoSomething();
   }
}

Así que lo que sucedió fue que la función del compilador inlined DoSomething y todas las asignaciones de pila estaban sucediendo dentro de la función Process() y, por lo tanto, volaban la pila. En mi defensa (y yo no era el uno que encontró el problema, tuve que ir y llorar a uno de los desarrolladores senior cuando no pude solucionarlo), no era recta alloca, era una de las macros de conversión de cadenas ATL.

Así que la lección es - no use alloca en funciones que cree que podrían estar en línea.

 169
Author: Igor Zevaka,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2010-08-04 23:35:07

Vieja pregunta pero nadie mencionó que debería ser reemplazada por arrays de longitud variable.

char arr[size];

En lugar de

char *arr=alloca(size);

Está en el estándar C99 y existió como extensión de compilador en muchos compiladores.

 57
Author: Patrick Schlüter,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-12-12 10:19:37

Alloca() es muy útil si no puede usar una variable local estándar porque su tamaño tendría que determinarse en tiempo de ejecución y puede garantiza absolutamente que el puntero que obtienes de alloca() NUNCA se usará después de que esta función devuelva.

Puede estar bastante seguro si

  • no devuelva el puntero, ni nada que lo contenga.
  • no almacene el puntero en ninguna estructura asignada en el montón
  • no deje que ningún otro hilo use el pointer

El verdadero peligro proviene de la posibilidad de que alguien más viole estas condiciones en algún momento después. Con eso en mente, es ideal para pasar búferes a funciones que formatean texto en ellos:)

 49
Author: Arthur Ulfeldt,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-22 23:59:42

Como se señaló en este grupo de noticias publicar , hay algunas razones por las que usar alloca puede ser considerado difícil y peligroso:

  • No todos los compiladores soportan alloca.
  • Algunos compiladores interpretan el comportamiento pretendido de alloca de manera diferente, por lo que la portabilidad no está garantizada incluso entre compiladores que la soportan.
  • Algunas implementaciones tienen errores.
 37
Author: FreeMemory,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-29 05:43:31

Un problema es que no es estándar, aunque está ampliamente soportado. En igualdad de condiciones, siempre usaría una función estándar en lugar de una extensión de compilador común.

 25
Author: David Thornley,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-19 16:35:44

Todavía se desaconseja el uso de alloca, ¿por qué?

No percibo tal consenso. Muchos pros fuertes; algunos contras:

  • C99 proporciona matrices de longitud variable, que a menudo se usarían preferentemente como la notación más consistente con matrices de longitud fija y en general intuitiva
  • muchos sistemas tienen menos memoria/espacio de direcciones disponible para la pila que para el montón, lo que hace que el programa sea un poco más susceptible al agotamiento de la memoria (a través del desbordamiento de la pila): esto puede verse como algo bueno o malo - una de las razones por las que la pila no crece automáticamente de la manera que lo hace la pila es para evitar que los programas fuera de control tengan tanto impacto adverso en toda la máquina
  • cuando se usa en un ámbito más local (como un bucle while o for) o en varios ámbitos, la memoria se acumula por iteración / ámbito y no se libera hasta que la función sale: esto contrasta con las variables normales definido en el ámbito de una estructura de control (por ejemplo, for {int i = 0; i < 2; ++i) { X } acumularía alloca-ed la memoria solicitada en X, pero la memoria para una matriz de tamaño fijo se reciclaría por iteración).
  • los compiladores modernos normalmente no hacen inline funciones que llaman a alloca, pero si las fuerzas entonces el alloca sucederá en el contexto de los llamantes (es decir, la pila no se liberará hasta que el llamante regrese)
  • hace mucho tiempo alloca hizo la transición de una función / hack no portátil a una extensión estandarizada, pero puede persistir cierta percepción negativa
  • la vida útil está vinculada al ámbito de la función, que puede o no adaptarse al programador mejor que el control explícito malloc
  • tener que usar malloc anima a pensar en la desasignación : si eso se administra a través de una función de envoltura (por ejemplo, WonderfulObject_DestructorFree(ptr)), entonces la función proporciona un punto para las operaciones de limpieza de implementación (como cerrar descriptores de archivos, liberar punteros internos o hacer algunos registros) sin cambios explícitos en el cliente código: a veces es un buen modelo para adoptar consistentemente
    • en este estilo pseudo-OO de programación, es natural querer algo como WonderfulObject* p = WonderfulObject_AllocConstructor(); - eso es posible cuando el "constructor" es una función que devuelve malloc-memoria ed (ya que la memoria permanece asignada después de que la función devuelve el valor que se almacenará en p), pero no si el" constructor " utiliza alloca
      • una versión macro de WonderfulObject_AllocConstructor podría lograr esto, pero "las macros son malas" en el sentido de que pueden entrar en conflicto entre sí y código no macro y crear sustituciones no deseadas y los consiguientes problemas difíciles de diagnosticar
    • las operaciones que faltan free pueden ser detectadas por ValGrind, Purify, etc. pero las llamadas "destructor" faltantes no siempre se pueden detectar - un beneficio muy tenue en términos de cumplimiento del uso previsto; algunas implementaciones alloca() (como las de GCC) usan una macro en línea para alloca(), por lo que la sustitución en tiempo de ejecución de una biblioteca de diagnóstico de uso de memoria no es posible malloc/realloc/free (por ejemplo, cerca eléctrica)
  • algunas implementaciones tienen problemas sutiles: por ejemplo, desde la página de manual de Linux:

    En muchos sistemas alloca() no se puede usar dentro de la lista de argumentos de una llamada a una función, porque el espacio de pila reservado por alloca() aparecería en la pila en el medio del espacio para los argumentos de la función.


Sé que esta pregunta está etiquetada con C, pero como programador de C++ pensé que usaría C++ para ilustrar la utilidad potencial de alloca: el siguiente código (y aquí en ideone) crea un vector de seguimiento de tipos polimórficos de diferente tamaño que se asignan a la pila (con la vida útil vinculada al retorno de la función) en lugar de a la pila asignada.

#include <alloca.h>
#include <iostream>
#include <vector>

struct Base
{
    virtual ~Base() { }
    virtual int to_int() const = 0;
};

struct Integer : Base
{
    Integer(int n) : n_(n) { }
    int to_int() const { return n_; }
    int n_;
};

struct Double : Base
{
    Double(double n) : n_(n) { }
    int to_int() const { return -n_; }
    double n_;
};

inline Base* factory(double d) __attribute__((always_inline));

inline Base* factory(double d)
{
    if ((double)(int)d != d)
        return new (alloca(sizeof(Double))) Double(d);
    else
        return new (alloca(sizeof(Integer))) Integer(d);
}

int main()
{
    std::vector<Base*> numbers;
    numbers.push_back(factory(29.3));
    numbers.push_back(factory(29));
    numbers.push_back(factory(7.1));
    numbers.push_back(factory(2));
    numbers.push_back(factory(231.0));
    for (std::vector<Base*>::const_iterator i = numbers.begin();
         i != numbers.end(); ++i)
    {
        std::cout << *i << ' ' << (*i)->to_int() << '\n';
        (*i)->~Base();   // optionally / else Undefined Behaviour iff the
                         // program depends on side effects of destructor
    }
}
 21
Author: Tony Delroy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-05-23 02:50:57

Todas las otras respuestas son correctas. Sin embargo, si lo que desea asignar usando alloca() es razonablemente pequeño, creo que es una buena técnica que es más rápido y más conveniente que usar malloc() o de otra manera.

En otras palabras, alloca( 0x00ffffff ) es peligroso y probable que cause desbordamiento, exactamente tanto como char hugeArray[ 0x00ffffff ]; lo es. Sé prudente y razonable y estarás bien.

 11
Author: JSBձոգչ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-19 16:32:27

Todo el mundo ya ha señalado la gran cosa que es el comportamiento indefinido potencial de un desbordamiento de pila, pero debo mencionar que el entorno de Windows tiene un gran mecanismo para atrapar esto utilizando excepciones estructuradas (SEH) y páginas de guardia. Dado que la pila solo crece según sea necesario, estas páginas de guardia residen en áreas que no están asignadas. Si se asigna a ellos (desbordando la pila) se lanza una excepción.

Puede capturar esta excepción SEH y llamar a _resetstkoflw para restablecer la pila y continuar en su camino feliz. No es ideal, pero es otro mecanismo para al menos saber que algo ha salido mal cuando las cosas golpean el ventilador. * nix podría tener algo similar de lo que no soy consciente.

Recomiendo limitar su tamaño máximo de asignación envolviendo alloca y rastreándolo internamente. Si usted era realmente hardcore sobre él usted podría lanzar algunos centinelas de alcance en la parte superior de su función para rastrear cualquier asignación alloca en el ámbito de la función y la cordura comprobar esto contra la cantidad máxima permitida para su proyecto.

Además, además de no permitir fugas de memoria alloca no causa fragmentación de memoria que es bastante importante. No creo que alloca sea una mala práctica si la usas inteligentemente, lo cual es básicamente cierto para todo. :-)

 11
Author: SilentDirge,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-03-21 16:19:04

He aquí por qué:

char x;
char *y=malloc(1);
char *z=alloca(&x-y);
*z = 1;

No es que alguien escribiera este código, pero el argumento de tamaño que estás pasando a alloca casi seguramente proviene de algún tipo de entrada, que podría tener como objetivo malintencionado conseguir que tu programa alloca algo enorme como eso. Después de todo, si el tamaño no se basa en la entrada o no tiene la posibilidad de ser grande, ¿por qué no declaraste un búfer local pequeño y de tamaño fijo?

Prácticamente todo el código que usa alloca y/o vlas C99 tiene errores graves que llevarán a se bloquea (si tienes suerte) o se compromete el privilegio (si no tienes tanta suerte).

 9
Author: R..,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-01-06 06:30:38

Alloca () es agradable y eficiente... pero también está profundamente roto.

  • comportamiento de ámbito roto (ámbito de función en lugar de ámbito de bloque)
  • use inconsistente con malloc (alloca () - el puntero ted no debe ser liberado, de ahora en adelante debe rastrear de dónde vienen los punteros a free () solo aquellos que tiene con malloc())
  • mal comportamiento cuando también se usa inlining (scope a veces va a la función de llamada dependiendo de si el en línea o no).
  • no hay verificación de límites de pila
  • comportamiento indefinido en caso de fallo (no devuelve NULL como malloc... y lo que significa fracaso, ya que no comprueba los límites de la pila de todos modos...)
  • no estándar ansi

En la mayoría de los casos puede reemplazarlo usando variables locales y tamaño mayor. Si se usa para objetos grandes, colocarlos en el montón suele ser una idea más segura.

Si realmente lo necesitas C puedes usar VLA (no vla en C++, qué pena). Le son mucho mejores que alloca() con respecto al comportamiento y consistencia del ámbito. Como yo lo veo VLA son una especie de alloca() hecho a la derecha.

Por supuesto, una estructura local o array usando un majorant del espacio necesario es aún mejor, y si no tienes tal asignación de montón de majorant usando malloc() es probablemente sano. No veo ningún caso de uso en el que realmente necesite alloca() o VLA.

 9
Author: kriss,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-12-17 08:48:02

Muchas respuestas interesantes a esta "vieja" pregunta, incluso algunas respuestas relativamente nuevas, pero no encontré ninguna que mencione esto....

Cuando se utiliza correctamente y con cuidado, uso consistente de alloca() (tal vez en toda la aplicación) para manejar pequeñas asignaciones de longitud variable (o VLAs C99, cuando estén disponibles) puede conducir a una pila general más baja growth que una implementación de otro modo equivalente usando oversized arrays locales de longitud fija. Así que alloca() puede ser bueno para su pila si lo usa con cuidado.

Encontré esa cita en.... Vale, inventé esa cita. Pero en serio, piénsalo....

@j_random_hacker tiene mucha razón en sus comentarios bajo otras respuestas: Evitar el uso de alloca() en favor de matrices locales sobredimensionadas no hace que su programa esté más seguro de los desbordamientos de pila (a menos que su compilador sea lo suficientemente viejo para permitir la inserción de funciones que usan alloca() en cuyo caso debe actualizar, o a menos que use alloca() bucles internos, en cuyo caso debería hacerlo... no usar alloca() dentro de bucles).

He trabajado en entornos de escritorio/servidor y sistemas embebidos. Muchos sistemas embebidos no usan un montón en absoluto (ni siquiera se enlazan para apoyarlo), por razones que incluyen la percepción de que la memoria asignada dinámicamente es mala debido a los riesgos de fugas de memoria en una aplicación que nunca se reinicia durante años, o la justificación más razonable de que la memoria dinámica es peligrosa porque no se puede saber con certeza que una aplicación nunca fragmentará su montón hasta el punto de agotamiento de la memoria falsa. Así que los programadores embebidos se quedan con pocas alternativas.

alloca() (o VLAs) puede ser la herramienta adecuada para el trabajo.

He visto una y otra vez donde un programador hace un búfer asignado a la pila "lo suficientemente grande como para manejar cualquier caso posible". En un árbol de llamadas profundamente anidado, el uso repetido de eso (anti-?) patrón conduce al uso exagerado pila. (Imagine un llame al árbol de 20 niveles de profundidad, donde en cada nivel por diferentes razones, la función asigna ciegamente un búfer de 1024 bytes "solo para estar seguro" cuando generalmente solo usará 16 o menos de ellos, y solo en casos muy raros puede usar más.) Una alternativa es usar alloca() o VLAs y asignar solo tanto espacio de pila como su función necesite, para evitar sobrecargar innecesariamente la pila. Esperemos que cuando una función en el árbol de llamadas necesita una asignación más grande de lo normal, otras en el árbol de llamadas son aún usando sus asignaciones pequeñas normales, y el uso general de la pila de aplicaciones es significativamente menor que si cada función asignara ciegamente un búfer local.

Pero si elige usar alloca()...

Basado en otras respuestas en esta página, parece que las VLAS deberían ser seguras (no componen las asignaciones de pila si se llaman desde dentro de un bucle), pero si está utilizando alloca(), tenga cuidado de no usarlo dentro de un bucle, y asegúrese de que su función no hay alguna posibilidad de que pueda ser llamado dentro del bucle de otra función.

 9
Author: phonetagger,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-31 22:25:32

Un lugar donde alloca() es especialmente peligroso que malloc() es el núcleo: el núcleo de un sistema operativo típico tiene un espacio de pila de tamaño fijo codificado en una de sus cabeceras; no es tan flexible como la pila de una aplicación. Hacer una llamada a alloca() con un tamaño injustificado puede causar que el núcleo se bloquee. Ciertos compiladores advierten el uso de alloca() (e incluso VLAs para el caso) bajo ciertas opciones que deben activarse mientras se compila un código del núcleo - aquí, es mejor asignar memoria en el montón que no está fijada por un límite codificado.

 7
Author: Sondhi Chakraborty,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-10-13 11:01:01

Tristemente el verdaderamente impresionante alloca() falta en el casi impresionante tcc. Gcc tiene alloca().

  1. Siembra la semilla de su propia destrucción. Con return como destructor.

  2. Como malloc() devuelve un puntero no válido en fallar que le violación de segmento en los sistemas modernos con una MMU (y esperemos que reiniciar aquellos sin).

  3. A diferencia de las variables automáticas, puede especificar el tamaño en tiempo de ejecución.

Funciona bien con recursión. Puedes use variables estáticas para lograr algo similar a la recursión de cola y use solo algunas otras para pasar información a cada iteración.

Si usted empuja demasiado profundo usted está asegurado de un segfault (si usted tiene un MMU).

Tenga en cuenta que malloc() no ofrece más, ya que devuelve NULL (que también se segmentará si se asigna) cuando el sistema se queda sin memoria. Es decir, todo lo que puede hacer es pagar la fianza o simplemente tratar de asignarlo de cualquier manera.

Para usar malloc() utilizo globals y les asigno NULL. Si el puntero no es NULL I libre antes de usar malloc().

También puede usar realloc() como caso general si desea copiar cualquier dato existente. Es necesario comprobar puntero antes de averiguar si va a copiar o concatenar después de la realloc().

3.2.5.2 Ventajas de alloca

 4
Author: zagam,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-02-10 22:52:00

Si accidentalmente escribe más allá del bloque asignado con alloca (debido a un desbordamiento de búfer, por ejemplo), entonces sobrescribirá la dirección de retorno de su función, porque esa se encuentra "arriba" en la pila, es decir, después de su bloque asignado.

_alloca bloque en la pila

La consecuencia de esto es doble:

  1. El programa se bloqueará espectacularmente y será imposible decir por qué o dónde se bloqueó (la pila lo más probable es desenrolle a una dirección aleatoria debido al puntero de marco sobrescrito).

  2. Hace que el desbordamiento de búfer sea muchas veces más peligroso, ya que un usuario malicioso puede crear una carga útil especial que se pondría en la pila y, por lo tanto, puede terminar ejecutada.

Por el contrario, si escribes más allá de un bloque en el montón, "solo" obtendrás corrupción en el montón. El programa probablemente terminará inesperadamente, pero desenrollará la pila correctamente, reduciendo así la posibilidad de código malicioso ejecución.

 4
Author: rustyx,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-07-03 14:09:56

No creo que nadie haya mencionado esto: El uso de alloca en una función obstaculizará o deshabilitará algunas optimizaciones que de otra manera podrían aplicarse en la función, ya que el compilador no puede saber el tamaño del marco de pila de la función.

Por ejemplo, una optimización común de los compiladores de C es eliminar el uso del puntero de marco dentro de una función, los accesos de marco se hacen en relación con el puntero de pila; por lo que hay un registro más para uso general. Pero si se llama alloca dentro de la función, la diferencia entre sp y fp será desconocida para parte de la función, por lo que esta optimización no se puede hacer.

Dada la rareza de su uso, y su estado sombreado como una función estándar, los diseñadores del compilador posiblemente deshabiliten cualquier optimización que podría causar problemas con alloca, si tomaría más que un pequeño esfuerzo para que funcione con alloca.

 4
Author: greggo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-18 19:11:45

Una trampa con alloca es que longjmp lo rebobina.

Es decir, si guardas un contexto con setjmp, luego alloca algo de memoria, luego longjmp al contexto, puedes perder la memoria alloca (sin ningún tipo de aviso). El puntero de la pila está de vuelta donde estaba y, por lo tanto, la memoria ya no está reservada; si llama a una función o hace otra alloca, golpeará el alloca original.

Para aclarar, a lo que me estoy refiriendo específicamente aquí es una situación en la que longjmp no volver fuera de la función donde el alloca tuvo lugar! Más bien, una función guarda el contexto con setjmp; luego asigna la memoria con alloca y finalmente se lleva a cabo un longjmp a ese contexto. La memoria alloca de esa función no es toda liberada; solo toda la memoria que asignó desde el setjmp. Por supuesto, estoy hablando de un comportamiento observado; no se documenta tal requisito de ningún alloca que yo conozca.

El enfoque en la documentación suele ser el concepto de que alloca la memoria es asociado con una activación de function, no con ningún bloque; que las múltiples invocaciones de alloca simplemente captan más memoria de pila que se libera cuando la función termina. No es así; la memoria está realmente asociada con el contexto del procedimiento. Cuando el contexto se restaura con longjmp, también lo es el estado anterior alloca. Es una consecuencia de que el propio registro de puntero de pila se utiliza para la asignación, y también (necesariamente) guardado y restaurado en el jmp_buf.

Incidentalmente, esto, si funciona de esa manera, proporciona un mecanismo plausible para liberar deliberadamente la memoria que se asignó con alloca.

Me he encontrado con esto como la causa raíz de un error.

 4
Author: Kaz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-09-18 02:25:01

Los procesos solo tienen una cantidad limitada de espacio de pila disponible, mucho menos que la cantidad de memoria disponible para malloc().

Al usar alloca() aumentas drásticamente tus posibilidades de obtener un error de Desbordamiento de pila (si tienes suerte, o un bloqueo inexplicable si no lo eres).

 3
Author: RichieHindle,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-19 16:27:46

No es muy bonito, pero si el rendimiento realmente importa, podría preasignar algo de espacio en la pila.

Si ya ahora el tamaño máximo de la memoria bloquea su necesidad y desea mantener las comprobaciones de desbordamiento, podría hacer algo como:

void f()
{
    char array_on_stack[ MAX_BYTES_TO_ALLOCATE ];
    SomeType *p = (SomeType *)array;

    (...)
}
 2
Author: Sylvain Rodrigue,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2009-06-19 17:21:29

En realidad, alloca no está garantizado para usar la pila. De hecho, la implementación gcc-2.95 de alloca asigna memoria del montón usando malloc en sí. También que la implementación es defectuosa, puede conducir a una fuga de memoria y a algún comportamiento inesperado si lo llamas dentro de un bloque con un uso adicional de goto. No, para decir que nunca debe usarlo, pero algunas veces alloca conduce a más sobrecarga de lo que libera frome.

 2
Author: user7491277,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-01-30 18:14:22

En mi humilde opinión, alloca se considera una mala práctica porque todo el mundo tiene miedo de agotar el límite de tamaño de la pila.

Aprendí mucho leyendo este hilo y algunos otros enlaces:

Uso alloca principalmente para hacer mis archivos C simples compilables en msvc y gcc sin ningún cambio, estilo C89, sin # ifdef _MSC_VER, etc.

¡Gracias ! Este hilo me hizo registrarme en este sitio:)

 0
Author: ytoto,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:18:25

La función alloca es grande y todos los detractores están simplemente esparciendo FUD.

void foo()
{
    int x = 50000; 
    char array[x];
    char *parray = (char *)alloca(x);
}

Array y parray son EXACTAMENTE iguales con EXACTAMENTE los mismos riesgos. Decir que uno es mejor que otro es una elección sintáctica, no técnica.

En cuanto a la elección de variables de pila vs variables de montón, hay MUCHAS ventajas para los programas de larga ejecución que utilizan pila sobre montón para las variables con vida dentro del ámbito. Evita la fragmentación del montón y puede evitar el crecimiento de su proceso espacio con espacio de montón no utilizado (inutilizable). No necesitas limpiarlo. Puede controlar la asignación de la pila en el proceso.

¿Por qué es esto malo?

 0
Author: mlwmohawk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-13 21:10:51

En mi opinión, alloca(), cuando esté disponible, debe usarse solo de manera limitada. Al igual que el uso de "goto", un gran número de personas por lo demás razonables tienen una fuerte aversión no solo al uso, sino también a la existencia de alloca().

Para uso embebido, donde se conoce el tamaño de la pila y se pueden imponer límites mediante convención y análisis sobre el tamaño de la asignación, y donde el compilador no se puede actualizar para soportar C99+, el uso de alloca () está bien, y He sido conocido por usarlo.

Cuando está disponible, las VLAs pueden tener algunas ventajas sobre alloca(): El compilador puede generar comprobaciones de límite de pila que capturarán el acceso fuera de los límites cuando se use el acceso de estilo array (no se si algún compilador hace esto, pero se puede hacer), y el análisis del código puede determinar si las expresiones de acceso a array están correctamente delimitadas. Tenga en cuenta que, en algunos entornos de programación, como automoción, equipos médicos y aviónica, este análisis tiene que ser hecho incluso para matrices de tamaño fijo, tanto automáticas (en la pila) como estáticas (globales o locales).

En arquitecturas que almacenan tanto datos como direcciones de retorno/punteros de marco en la pila (por lo que sé, eso es todo), cualquier variable asignada a la pila puede ser peligrosa porque la dirección de la variable se puede tomar, y los valores de entrada sin marcar pueden permitir todo tipo de travesuras.

La portabilidad es menos preocupante en el espacio embebido, sin embargo, es un buen argumento contra el uso de alloca() fuera de circunstancias cuidadosamente controladas.

Fuera del espacio embebido, he utilizado alloca() principalmente dentro de las funciones de registro y formato para la eficiencia, y en un escáner léxico no recursivo, donde las estructuras temporales (asignadas usando alloca() se crean durante la tokenización y clasificación, luego un objeto persistente (asignado a través de malloc()) se rellena antes de que regrese la función. El uso de alloca() para las estructuras temporales más pequeñas en gran medida reduce la fragmentación cuando se asigna el objeto persistente.

 0
Author: Daniel Glasser,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-12-13 14:36:17

La mayoría de las respuestas aquí en gran medida pasan por alto el punto: hay una razón por la que usar _alloca() es potencialmente peor que simplemente almacenar objetos grandes en la pila.

La principal diferencia entre el almacenamiento automático y _alloca() es que este último sufre de un problema adicional (grave): el bloque asignado es no controlado por el compilador, por lo que no hay forma de que el compilador lo optimice o recicle.

Comparar:

while (condition) {
    char buffer[0x100]; // Chill.
    /* ... */
}

Con:

while (condition) {
    char* buffer = _alloca(0x100); // Bad!
    /* ... */
}

El problema con el esto último debería ser obvio.

 -1
Author: alecov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-28 14:31:41