Pregunta de C

Horst von Brand vonbrand en inf.utfsm.cl
Mie Mayo 10 00:37:57 CLT 2006


Alvaro Herrera <alvherre en alvh.no-ip.org> wrote:
> [Republicando desde la lista oss-devel en listas.ubiobio.cl]
> 
> Tengo una duda.  Supongase la funcion siguiente:
> 
> void
> pgr_formtuple(Relation foo)
> {
> 	int		natt = foo->natts;
> 	char    arr[natt];
> 	char	nulls[natt];
> 
> 	...
> }
> 
> Se aprecia que las variables arr y nulls son creadas como arreglos del
> tamaño especificado que no es constante en tiempo de compilacion, sino
> que se determina en tiempo de ejecucion dependiendo del contenido del
> struct Relation.
> 
> Es valido esto?  Debo mencionar que compila perfectamente sin ningun
> warning (con varias opciones -W), y que funciona perfectamente para
> algunos valores de foo->natts.  Sin embargo, el programa se cae en un
> caso muy particular que es cuando foo->natts es 61, un valor superior a
> los valores tipicos.  (natts es el numero de columnas de una tabla; por
> lo tanto 61 es un valor perfectamente valido pero tipicamente los
> valores andan cercanos a la veintena).

Me parece que es una extension de GCC, y que es valido en C99 (-std=c99
para GCC)

> Hay que hacer notar que la caida ocurre en codigo que no esta en el
> ejemplo, pero es demasiado extenso para ponerlo aca.  (Puedo hacerlo si
> alguien cree que vale la pena).

Caida como en que? Huele a una rana de GCC... Algunas luces de un backtrace
(archivo core, gdb(1) les hace chupete ;-)? O hacer que se caiga bajo el
control de gdb(1) (a veces la caida enreda las estructuras, y el debugger
se confunde y cuenta historias muy creativas pero irrelevantes; puedes
attachar gdb a un proceso en ejecucion si se demora demasiado en llegar
alli). Si, /es/ posible compilar con optimizacion y -g en GCC, claro que al
"optimizar" se enredan las cosas, y hay que tener cuidado al correlacionar
lineas fuente y ejecucion del programa (pueden desaparecer lineas (incluso
variables completas con sus usos!), lineas que se replican, operaciones que
se cambian por cosas muy diferentes, ejecucion que salta sin ton ni son de
una linea a otra, ...).

> [Solucion con malloc()]

Notese que malloc(3)/free(3) es relativamente costoso...

> Pero me queda la duda si lo de arriba es realmente erroneo.  Por otra
> parte, yo se que lo siguiente si funciona:
> 
> 
> void
> pgr_formtuple(Relation foo)
> {
> 	int		natt = foo->natts;
> 
> 	{
> 		char    arr[natt];
> 		char	nulls[natt];
> 
> 		...
> 	}
> }

> Aca la consideracion es que las variables estan creadas en un stack que
> es interior al lugar donde se declara el tamaño que tendran las
> variables.  Pero no se si esto realmente influya o sea solamente
> cosmetico.

Es puramente (anti)cosmetico. Si esto funciona, y lo otro no, saldria a
buscar (bueno, en realidad en ambos casos):

- Areas en las que podria estarse rebalsando algo (y pisar tu arreglo, o
  viceversa), o usos de variables que ya se eliminaron (un stack mas grande
  podria volver a cubrir areas que se liberaron antes, y "corromper" lo que
  se estaba usando impunemente)
  [Los tontorrones de Coverity no le hacen a PostgreSQL?]
- Es esto parte de una cadena larga de llamadas? Podria producir problemas
  de rebalse de stack...
- Comparar el codigo assembler que genera en ambas opciones (no debieran
  haber diferencias, realmente; si las hay, se me hace sospechoso el
  compilador...)

> Cualquier comentario es bienvenido.

Seria entretenido mirarlo, pero para eso se requiere tiempo... :-(
-- 
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