GCC er dum

Når jeg har udviklet C/C++ kode, så har jeg altid anvendt "-Wall" som compiler argument til gcc (eller g++) - for så fanger jeg jo så meget som muligt - men nej, Under et større udviklingsprojekt fandt jeg ud af at gcc er lidt dum og man kan gå lidt i vandet her.

Se på nedenstående C-kode (gem den som foo.c), hvor jeg bevidst laver den fejl at variablen "j" ikke er initialiseret før den bruges. Nem fejl at finde troede jeg. Når man kalder "gcc -g -Wall -o foo foo.c", burde gcc fange den fejl. Men nej - ingen fejl i koden.
Hvis man i stedet oversætter koden med "gcc -g -Wall -O -o foo foo.c", så får jeg fint at

  • foo.c: In function 'main':
  • foo.c:11: warning: 'j' is used uninitialized in this function

include

/* Gem som "foo.c" /
/
gcc -g -Wall -O -o foo foo.c /
/
gcc -g -Wall -o foo foo.c */

int main(void)
{
int i,j;

i=j+2; /* fejl - j er ikke initialiseret /
printf("i=%i\n",i); /
udprintning af variabel som ikke er initialiseret */

return 0;
}

Så er der vel ikke noget problem i det? Brug dog også "-O", men her kommer man ind i et andet problem. Når man debugger koden med gdb eller ddd, så ryger der ofte variable i optimeringen (dvs. "-O").

pto@petertoft:~/c > gdb ./foo
GNU gdb 6.4.90-debian
Copyright (C) 2006 Free Software Foundation, Inc.
GDB is free software, covered by the GNU General Public License, and you are
welcome to change it and/or distribute copies of it under certain conditions.
Type "show copying" to see the conditions.
There is absolutely no warranty for GDB. Type "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...Using host libthread_db library "/lib/tls/libthread_db.so.1".

(gdb) start
Breakpoint 1 at 0x8048365: file foo.c, line 12.
Starting program: /home/pto/c/foo
Failed to read a valid object file image from memory.
main () at foo.c:12
12 printf("i=%i\n",i); /* udprintning af variabel som ikke er initialiseret */
(gdb) print i
No symbol "i" in current context.

Øv øv øv - simple variable forsvinder ofte med "-O", og jeg kan ikke både holde fuld debug information og samtidig have detektion af ikke-initialiserede variable. Det er dumt....

Den måde jeg pt. håndterer C/C++ kode i udviklingsfasen er at anvende "gcc -g -o foo foo.c", så jeg har alle symboler under debug-fasen - og så anvender jeg fra tid til anden "gcc -g -Wall -O -o foo foo.c" så jeg kan se fejl med ikke initialiserede variable. Det skal lige nævnes at mine projekter har omkring 100 C-filer i et hav af underkataloger, så ovenstående eksempel er meget forsimplet.

Er der nogen af jer som tackler de problemer lidt anderledes? Naturligvis anvender jeg også valgrind (eller purify og eller Insure++) - men den er en anden snak.

/pto

Kommentarer (7)
sortSortér kommentarer
  • Ældste først
  • Nyeste først
  • Bedste først
#1 Poul-Henning Kamp Blogger

GCC er dum på mange måder og det er meget tiltrængt at få noget konkurrence (se: llvm.org)

Hvis man ikke giver et -O argument bliver det meste af kodeanalsysen slået fra og således også en masse check for fejl som den du kigger på.

Jeg bruger selv FlexeLint (www.gimpel.com) for at få en "second opinion" og selvom den koster $1000 for en etbruger licens, så kan jeg varmt anbefale den.

Poul-Henning

  • 0
  • 0
#4 Søren Hansen

Hej Peter

Hvis du læste manualen til GCC ser du også flg:

-Wuninitialized (only with -O1 and above)

-Wall er blot en samling af alle de forskellige warnings, den kan finde på at finde - og således også uninitialized.

Vær i øvrigt også lige opmærksom på:

-Warray-bounds (only with -O2)

Dette er advarsler, som compileren først finder, når den har kørt de ekstra iterationer, som du beder om at køre ved optimering. Er der nogen der ved, om man kan få gcc til at køre disse iterationer UDEN rent faktisk at optimere undervejs?

  • 0
  • 0
#5 Poul-Henning Kamp Blogger

LLVM er interessant fordi den opfatter compileren som et værktøj istedet for en funktion.

Nogle af de ting Apple bruger LLVM til er virkelig kreative, f.eks just-in-time compilering af OpenGL primitiver som deres grafikchip ikke lige understøtter.

Vi fik en presentation af LLVM på BSDcan's devsummit og der var rigtig mange der spærrede øjnene op.

Jeg tror LLVM er kommet for at blive, men hvad det når at blive til må tiden vise.

Så længe GCC er under GPLv3, så er der ingen tvivl om at LLVM har nemt ved at tiltrække interesse.

Poul-Henning

  • 0
  • 0
#6 Peter Toft

Jeps - og det er netop det problem jeg peger på. Under en udviklings/debug-fase er -Wall rart, men at den kræver -O2 eller -O1 er IMHO designmæssigt ærgeligt. I øvrigt tror jeg dit spørgsmål besvaret med "nej" - det er netop optimeringerne jeg gerne vil undgå, herunder at simple variable må fjernes (ofte simple afledte variable fra løkke-tællerne mv.). Det er bare så træls når man debugger at man mødes med "No symbol "i" in current context." eller lign.

  • 0
  • 0
#7 Lars Balker

Egentligt ikke særligt funktionelt at en -Warning er afhængig af sideeffekten af en -Optimering. En analyse burde være uafhængig af brugen, og kun/altid blive udført når der er behov for den, uanset om det er af den ene eller anden grund.

Nordøstamerikansk klytkode!

  • 0
  • 0
Log ind eller Opret konto for at kommentere