2010-08-15 8 views
6

He leído bastantes lugares que alloca es obsoleto y no debe usarse y en su lugar se deben usar matrices de longitud variable.¿Es alloca completamente reemplazable?

Mi pregunta es esta: ¿Es alloca completamente reemplazable por matrices de longitud variable?

En mi caso particular tengo algo que se parece a esto:

typedef struct { 
    int *value; 
    size_t size; 
    } some_type; 

void SomeExternalFunction(some_type); 

... 

void foo(){ 
    //What I thought to do 
    some_type bar; 
    bar.value=alloca(sizeof(int)*10); 
    SomeExternalFunction(bar); 

    //what should be done without alloca 
    some_type fizz; 
    int tmp[10]; 
    fizz.value=tmp; 
    SoemExternalFunction(fizz); 
} 

Me estoy perdiendo algo o se trata de un buen uso real de alloca? Supongamos también para este ejemplo que por alguna razón deseo que el valor se asigne en la pila

+4

Eso no es en realidad una matriz de longitud variable ... Como ha especificado una longitud constante. Y ... Incluso si * fuera * una longitud variable, realmente no estoy viendo qué alloca te compra aquí, aparte de hacer que la intención del código sea un poco más oscura. (Obviamente, si está utilizando un compilador que no admite matrices de longitud variable, no puede elegir entre las dos) – Shog9

+0

Vea también: http://stackoverflow.com/questions/3452434/in-which- casos-es-alloca-útil (sería un duplicado basado en el título, pero creo que realmente estás tratando de preguntar algo más ... no puedo decir qué) – Shog9

Respuesta

13

Hay una diferencia importante entre los VLA y alloca: La memoria alloca() devuelve es válida mientras la función actual persista. La vida útil de la memoria ocupada por un VLA es válida siempre que el identificador del VLA permanezca en el alcance. Puede asignar memoria alloca() en un bucle, por ejemplo, y usar la memoria fuera del bucle, un VLA desaparecería porque el identificador queda fuera del alcance cuando termina el bucle. Esto significa, que usted puede hacer esto con alloca() y suficiente espacio de pila:

typedef struct node { int data; struct node *next; }; 
void fun() 
{ 
struct node *n=0; 
int d; 
/* Now we are building a single-linked list on the stack! */ 
while(d=get_something()) { 
    struct node *x=alloca(sizeof(*x)); 
    x->next=n; 
    x->data=d; 
    n=x; 
} 
do_something_with(n); 
} // and the whole thing is deleted here.. 

No se puede hacer esto con VLA.

+0

FWIW: esta sería una gran respuesta para ambos [¿En qué casos es útil alloca()?] (Http://stackoverflow.com/questions/3452434/in-which-cases-is-alloca-useful) y [¿Cuál es la diferencia entre alloca (n) y char x \ [n \]?] (http://stackoverflow.com/questions/2614561/whats-the-difference-between-allocan-and-char-xn) – Shog9

+0

Esta es una gran respuesta con respecto a la diferencia, pero es posible que también desee observar que el comportamiento de 'alloca' es esencialmente definido por la implementación ya que no está especificado en ningún estándar (actual). –

+0

Por cierto, ** hay ** una forma de hacer lo mismo con los VLA: haga que la función sea recursiva y llame a 'do_something_with (n)' en el nivel más profundo. :-) En realidad tenía un uso real para esto, que aún no he implementado: una implementación ligera de '/ lib/ld.so' que realiza un enlace dinámico en la pila para evitar llevar la sobrecarga de' malloc' a minúsculas programas que no lo usan Al final, se desenrollaría y descartaría todos los datos dinámicos de enlace si y solo si 'libdl' no se ha vinculado; de lo contrario, llamaría a '_start' desde el nivel más profundo de recursión. –

1

alloca es completamente reemplazable por malloc y free. Es un poco más de trabajo, pero a menos que sea muy cuidadoso, es esencial. Casi todos los códigos que usan alloca o C99 vla son vulnerables a los ataques de desbordamiento de la pila, y en muchas implementaciones, pueden conducir a la elevación de privilegios. No existe una forma portátil de saber qué tan grande es la pila o cuánto espacio queda (o cuánto overhead más allá del tamaño requerido podría ser necesario para el uso interno del compilador o para llamadas a funciones adicionales), por lo que lo único razonable que puede hacer para make vla's/alloca safe es imponer límites artificiales extremadamente pequeños al tamaño de los datos que admite (por ejemplo, algunos kb). En este punto, también podría estar usando objetos automáticos simples de longitud no variable ...

+0

Heap está reemplazando completamente a la pila. Nop. –

Cuestiones relacionadas