gcc bug?!?

Fórumok

Valaki magyarázza meg nekem ezt a gdb kimenetet, mert én nem értem...


debian:/home/xxxxxxxx# gdb enproggim
GNU gdb 6.8-debian
Copyright (C) 2008 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law. Type "show copying"
and "show warranty" for details.
This GDB was configured as "i486-linux-gnu"...
(gdb) run
Starting program: /home/xxxxxxxxxx/bin/enproggim
BAZZE l=109

Program received signal SIGSEGV, Segmentation fault.
0xb7efdd4d in db_connect (host=0x0, port=0, user=0x0, pass=0x0, db=0x8add2f8 "/home/xxxxxxxxx") at db_bin.c:81
81 if(!(dirname=malloc(l)))
(gdb) bt
#0 0xb7efdd4d in db_connect (host=0x0, port=0, user=0x0, pass=0x0, db=0x8add2f8 "/home/xxxxxxxxx") at db_bin.c:81
#1 0x08049862 in db_connect () at db.c:120
#2 0x0804e55c in main (argc=1, argv=0xbfbeb204) at main.c:80

No mégis, mi tud segfaultolni a 81. sorban?!? Nem a malloc, mert az nem szerepel a backtrace-ben. (Megj: azért van két db_connect, mert az egyik a wrapper, a másik a plugin-beli.)

Fordítás során használt kapcsolók, paraméterek (Makefile részlet):

OPT = -O1
CFLAGS = -Wall -g
DYNLIB = -shared -fpic
CC = gcc $(OPT) $(CFLAGS) $(DYNLIB)
db_bin.so: db_bin.c
@echo " PLG $<"
@$(CC) -lm $< -o $(<:.c=.so)

Forrás idevágó része:

void db_connect(char* host,int port,char *user,char *pass,char *db)
{
int i,l;
if(db==NULL) { *db_error="No database given!"; return; }
splitbins=-1; l=strlen(db);
for(i=0;i<l-5;i++) if(!strncmp(db+i,"_DATE_",6)) { splitbins=i; break; }
l+=64;
if(!(dbname=malloc(l))) { *db_error="Not enough memory."; return; }
else {
if(splitbins>=0){
printf("BAZZE l=%d\n",l); fflush(stdout);
if(!(dirname=malloc(l)))
{ *db_error="Not enough memory."; return; }

(Megj: a db_error változó egy char**, a char* a db.c van allokálva, és az init során átadódik a címe a pluginnak. Megj2: azért van az l+=64 sor, mert még hozzáfűznék a filenévhez ezt-azt)

Verziók:
gcc (Debian 4.3.2-1.1) 4.3.2
Linux debian 2.6.26-2-686 #1 SMP Wed Nov 4 20:45:37 UTC 2009 i686 GNU/Linux
/etc/debillány_version: 5.0.3

Flame elkerülése végett nem kódolási stílust kell fikázni, hanem gdb kimenetet megmagyarázni.
Ha valaki tudja a választ, az kap tőlem egy szóbeli csokit! Sőt, kettőt is!

Hozzászólások

ÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁÁ

megoldódott!

char *dirname=NULL;
if(!(dirname=malloc(l)))

helyett

char *dir=NULL;
if(!(dir=malloc(l)))

már nem segfaultol... A kérdés azonban továbbra is áll: ez most egy **** ***** **** csúnya gcc bug?!? (Megj: az egész kódban sehol nem szerepelt máshol dirname nevű változó. Ha meg fgv, akkor miért nem sírt be rá a gcc?)

Ahogy a bő szókincsű Pista bácsi mondta volt: "f@szt".
A típusa nem függvénypointer, hanem változó.

char *dirname;

és nem pedig

char* (*dirname)(void);

mellesleg ezzel tisztában is van a compiler, -Wall-ra sem ad warningot, a linker az, ami összekeveri, ráadásul az sem rinyál, hogy két azonos id-jű entitás van. Ez bug.

(Megjegyzem, ha igazad lenne, akkor már a compiler szólna, ugyanis szintaxisbeli különbség van a függvénypointer és a sima változópointer hívása közt, ez utóbbi után sosem állhat zárójel, míg az előbbinél mindig kell, hogy álljon. Ennyit erről.)

Ez az április 1 elég durva, fogtam egy második gcc bugot is:

u_int64_t a=0;
u_int64_t b=1;
a=b<<32;
printf("%x\n",a);

A fenti kód hibátlanul fordul 32 bites és 64 bites linuxon, de a 32 bites gcc hibás kódot a generál, a kimenete nem 10000, hanem 0. Rágugligztam, nagyon sokan anyáznak erre, csereszabatos javítás nincs.

A

%x
int

-et var (ami legalabbis Linuxon, gcc-vel 32 biten is, 64 biten is) 32 bites, az

u_int64_t

pedig 64 bites. Tessek

printf("%llx\n",a);

-et hasznalni, a

long long int

32 biten is, 64 biten is 64 bites.

Amugy ha megnezed, a tiedre panaszkodik is a gcc, hogy nem lesz jo:

$ gcc -Wall -o gccbug gccbug.c
gccbug.c: In function 'main':
gccbug.c:8: warning: format '%x' expects type 'unsigned int', but argument 2 has type 'u_int64_t'

Nalam mukodik:

[muszi@muszi temp]$ cat gccbug-fix.c
#include <stdio.h>
#include <sys/types.h>

int main(void) {
  u_int64_t a=0;
  u_int64_t b=1;
  a=b<<32;
  printf("%llx\n",a);
  return (0);
}
[muszi@muszi temp]$ gcc -Wall -o gccbug-fix gccbug-fix.c
[muszi@muszi temp]$ ./gccbug-fix
100000000
[muszi@muszi temp]$ gcc --version
gcc (GCC) 4.1.2 20061115 (prerelease) (Debian 4.1.1-21)
[muszi@muszi temp]$ uname -a
Linux muszi.kite.hu 2.6.33.1 #1 SMP Wed Mar 31 12:55:46 CEST 2010 i686 GNU/Linux

szerk: nem fugg az optimalizaciotol sem:

[muszi@muszi temp]$ gcc -Wall -O2 -o gccbug-fix gccbug-fix.c
[muszi@muszi temp]$ ./gccbug-fix
100000000

Én is megnéztem, de nálam is jó adat van a memóriában.

Egyébként a google kereséseden megnéztem az első pár linket, és egyik sem erről szólt. (Igazából a fele nem is gcc-ről)...

"...handing C++ to the average programmer seems roughly comparable to handing a loaded .45 to a chimpanzee." -- Ted Ts'o