Pregunta de C

Horst von Brand vonbrand en inf.utfsm.cl
Jue Mayo 11 17:15:20 CLT 2006


Alvaro Herrera <alvherre en commandprompt.com> wrote:
> Horst von Brand escribió:
> > rodrigo ahumada <rodahummont en yahoo.com.ar> wrote:
> > > > int buggy(struct foo *a_foo)
> > > > {
> > > >     int     tam = a_foo->bar;
> > > >     char   *valor[tam];
> > > >     int     canario = 0x7e7e7e7e;
> > > >     int     i;
> > 
> > > si gcc crea las variables siguiendo el orden en que se
> > > declaran, canario deberia estar por delante de valor:
> > > 
> > > [i][canario][  valor  ][tam]...
> > 
> > Crea las variables "hacia abajo" (en el tope) en el stack, cierto.

> Trate de ver lo que sucedia si ponia un canario abajo y otro arriba de
> la variable, o sea 
> 
> int	canario1 = 0x7e7e7e7e;
> char   *valor[tam];
> int	canario2 = 0xe7e7e7e7;

> Sin embargo, me lleve una sorpresa porque mostrando las posiciones de
> las variables en el stack, canario1 y canario2 aparecen junto con tam e
> i, pegadas al principio del stack, mientras que valor aparece mucho mas
> abajo!  Deduzco que el compilador se toma la libertad de reordenar las
> variables como le plazca.  Esto es asi tanto con -O0, como -O2 y sin
> especificar ninguna.

Oh, claro. El arreglo valor[] es especial, porque es de taman~o
variable. Lo mas simple es poner esa clase de leseras al tope (minimiza los
calculos raros que hay que hacer para ubicar variables). O sea, quedaria
algo del corte:
    
	----------
       [ canario1 ]
	----------
       [ *valor1  ]--+
	----------   |
    +--[ *valor2  ]  |
    |   ----------   |
    |  [ canario2 ]  |
    |   ----------   |
    |  [  v       ]<-+
    |  [   a      ]
    |  [    l     ]
    |  [     o    ]
    |  [      r   ]
    |  [       1  ]
    |   ----------
    +->[  v       ]
       [   a      ]
       [    l     ]
       [     o    ]
       [      r   ]
       [       2  ]
	----------

[...]

> > Para programas a nivel usuario el stack es inmenso de grande, asi que seria
> > muy muy raro que ocurriera eso.

> Bueno, el programa de ejemplo se cae con SIGSEGV cuando el "tam" es
> mayor que algo de 1900000 (casi 2000000 realmente), lo cual por supuesto
> es esperable.  (Esto en x86-64 eso si).

Aja. Creo que esa es la madre del cordero. 2e6 por 8 bytes son 16MiB, lo
que no es muy prudente andar acarreando en el stack.
-- 
Dr. Horst H. von Brand                   User #22616 counter.li.org
Departamento de Informatica                     Fono: +56 32 654431
Universidad Tecnica Federico Santa Maria              +56 32 654239
Casilla 110-V, Valparaiso, Chile                Fax:  +56 32 797513


Más información sobre la lista de distribución Linux