Ladění problému ve stacku

Ladislav Vaiz spam na nagano.cz
Pátek Září 17 08:03:27 CEST 2010


> Toto leccos naznačuje. Buď gcc generuje špatný kód (nepravděpodobné), anebo
> někde děláte něco, co nemá jasně definované chování, a při optimalizaci se to
> rozbije.
>
> Každopádně odsud těžko soudit co, takže zkusme ještě to gdb. Dejte si break
> někam na ten řádek s tím scandirem (při -O2 se stane, že ta proměnná předtím
> prostě neexistuje) a dejte „print &n“. 
Can't take address of "n" which isn't an lvalue.

> Dostanete adresu toho n a poté by mělo
> snad jít přidat watchpoint na tu adresu pomocí „watch * (int *) <adresa>“.
> Pokud to nepůjde, nejspíš to i řekne, proč (například, že n je v registru
> anebo že ještě neexistuje). V takovém případě zkuste prostě do kódu napsat
> „printf("0x%lx\n", &n);“. 
A heleme se, hw breakpointy už fungují :-)

(gdb) p &n
$1 = (int *) 0x7fff05621cec
(gdb) watch n
Hardware watchpoint 2: n
(gdb)

Ale moc to nepomohlo:

(gdb) c
Continuing.

Watchpoint 2 deleted because the program has left the block in
which its expression is valid.
menu_load_contest (dir=<value optimized out>, unused=<value optimized 
out>) at menu.c:105

Tato funkce volá tu naši, kde je n automatickou proměnnou. Takže chyba v 
tomto případě nenastane :-(

> Je samozřejmě možné, že se pak chyba přestane
> projevovat, a pak už asi bude nejlepší si prostě přečíst ten asm kód, co gcc
> vyrobí.
>   

Hmm, assemblerem jsem se zabyval naposledy před >10lety pod DOSem, 
linuxovou AT&T syntaxi jsem nějak nerozdýchal. Navíc zatím nebyl důvod 
lámat to přes koleno.

Chápu to ale dobře, že chyba nastane pouze když n je v registru? Pak to 
asi nebude přetečení pole v zásobníku, ale čuju problém v gcc. Byť se mi 
to zdá divné, je to gcc z distribuce, kterým patrně byla celá distribuce 
zkompilována.

Zkoušel jsem přidat volatile a chyba nenastává. Koukal jsem do 
assemblereu, bez volatile (když padá), se návratový kód uloží do %r13, s 
volatile do 0x14c(%rsp). Pokud to dobře chápu, tak v prvním případě do 
registru, ve druhém do stacku. Lze nějak disassamblovat celou funkci do 
souboru, abych mohl hledat, co se děje s %r13 ? Nebo na něj nastavit 
watchpoint?

Jaký druh programátorské chyby by mohl způsobit něco takového?

Láďa


Další informace o konferenci Linux