PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Schwerer bug gcc 4.0.2/4.1.0, oder doch mein Fehler?


SimonX
2006-03-17, 16:08:58
Probiert auf einem P3-800, wie auch auf meinem P4 mit SuSe 10 und gcc 4.0.2:

#include <stdio.h>
typedef struct A A;

struct A {
int no;
A *sub;
};

void main()
{ A sub={0, NULL};
A root={0, &sub};
A *pos=&root;

pos=&pos->sub[pos->no++];
printf("%d %d %p %p %p\n", root.no, sub.no, &root, &sub, pos);
}

<~/test> 55>gcc -O0 -o sadd sadd.c
sadd.c: In function ‘main’:
sadd.c:10: warning: return type of ‘main’ is not ‘int’
<~/test> 56>sadd
0 1 0xbffb7b84 0xbffb7b8c 0xbffb7b8c
<~/test> 57>gcc -v
Using built-in specs.
Target: i586-suse-linux
Configured with: ../configure --enable-threads=posix --prefix=/usr --with-local-
prefix=/usr/local --infodir=/usr/share/info --mandir=/usr/share/man --libdir=/us
r/lib --libexecdir=/usr/lib --enable-languages=c,c++,objc,f95,java,ada --disable
-checking --with-gxx-include-dir=/usr/include/c++/4.0.2 --enable-java-awt=gtk --
disable-libjava-multilib --with-slibdir=/lib --with-system-zlib --enable-shared
--enable-__cxa_atexit --without-system-libunwind --host=i586-suse-linux
Thread model: posix
gcc version 4.0.2 20050901 (prerelease) (SUSE Linux)
<~/test> 58>

<~/test> 58>/usr/local/gcc-4.1.0/bin/gcc -O0 -o sadd sadd.c
sadd.c: In function ‘main’:
sadd.c:10: warning: return type of ‘main’ is not ‘int’
<~/test> 59>sadd
0 1 0xbf9a4ef0 0xbf9a4ef8 0xbf9a4ef8
<~/test> 60>/usr/local/gcc-4.1.0/bin/gcc -v
Using built-in specs.
Target: i586-suse-linux
Configured with: ../gcc-4.1.0/configure --prefix=/usr/local/gcc-4.1.0 --enable-java-awt=gtk --with-cpu=pentium4 --enable-threads=posix --enable-languages=c,c++,java --disable-checking --host=i586-suse-linux --disable-libjava-multilib --without-system-libunwind --with-system-zlib
Thread model: posix
gcc version 4.1.0
<~/test> 61>


Auf anderen Maschinen mit älteren gcc (gcc3.3.x und gcc3.4.x) gibt es das Problem nicht.
<~/test> >gcc -o sadd sadd.c
sadd.c: In function `main':
sadd.c:10: warning: return type of `main' is not `int'
<~/test> >sadd
1 0 11fffbfe0 11fffbfd0 11fffbfd0
<~/test> >gcc -v
Reading specs from /usr/local/gcc-3.3.1/lib/gcc-lib/alphaev68-dec-osf5.1/3.3.1/specs
Configured with: ../gcc-3.3.1/configure --prefix=/usr/local/gcc-3.3.1 --disable-shared
Thread model: single
gcc version 3.3.1


<~/test> >cc -o sadd sadd.c
<~/test> >sadd
1 0 11fffbfd8 11fffbfe8 11fffbfe8
<~/test> >cc -V
Compaq C V6.4-216 (dtk) on Compaq Tru64 UNIX V5.1A (Rev. 1885)
Compiler Driver V6.4-013 (dtk) cc Driver
<~/test> >

Ich probiere gleich mal den gcc-3.4.6 auf meinem Rechner aus.

Edit
Ach ja, der Bug is das no nicht von root hoch gezählt wird sondern von sub.

SimonX
2006-03-17, 16:36:02
Mit gcc-3.4.6 funktioniert es ohne Probleme:

<~/test> 89>/usr/local/gcc-3.4.6/bin/gcc -o sadd sadd.c
sadd.c: In function `main':
sadd.c:10: warning: return type of 'main' is not `int'
<~/test> 90>sadd
1 0 0xbfecd0b8 0xbfecd0c0 0xbfecd0c0

Coda
2006-03-17, 16:51:43
http://gcc.gnu.org/bugzilla/

SimonX
2006-03-17, 18:10:00
Das ist die Antwort:

------- Comment #1 From Andrew Pinski 2006-03-17 16:59 [reply] -------

pos=&pos->sub[pos->no++];


This is undefined. You assign pos and use it without a sequence point.

*** This bug has been marked as a duplicate of 11751 ***

Ich verstehe aber nicht wo da überhaupt ein sequence-point notwendig ist denn pos->no++ ist zu dem Zeitpunkt wo er benutzt wird klar definiert. Das sieht mir doch eher nach einem Problem im Code-Generator aus, da er einfach vergisst auf welchem pos->no das ++ auszuführen ist.

Coda
2006-03-17, 18:24:37
Hm es wurde anscheinend doch wieder geöffnet. Code-Generator glaube ich eher weniger, das sieht nach einem Frontend-Problem aus.

Edit: Könnte aber auch ein Problem sein, weil du ein Postincrement benützt. D.h. er kann entweder:

1) pos=&pos->sub[pos->no]; ++pos->no;
oder
2) temp = pos->no; ++pos->no; pos=&pos->sub[temp];

darunter verstehen. Es kann gut sein, dass das wirklich undefined ist.

Edit2: Ich glaube inzwischen er hat wirklich recht.

SimonX
2006-03-17, 18:51:37
Aber da ein spezielles pos->no doch schon benutzt wurde müsste doch die Operation ++ auch genau an diesem pos->no durchgeführt werden, egal ob der Access-Path (also der pos pointer) sich verändert hat.

Coda
2006-03-17, 21:22:16
Nein muss es nicht, da es ein Postincrement ist. Bei einem Preincrement wäre die Sache eindeutig.

Lass es einfach solchen Code zu schreiben. Die Evaluierungsreihenfolge ist da nicht festgelegt.

Gast
2006-03-18, 08:04:41
Kann man in bugzilla nicht noch sagen, dass der gcc da eine Warnung ausgeben sollte?

Neomi
2006-03-18, 13:15:38
Die Evaluierungsreihenfolge ist da nicht festgelegt.

In dem Fall eigentlich schon: "pos=&pos->sub[pos->no++];"

1. Die Anweisung in den eckigen Klammern muß zuerst ausgewertet werden, da der Rest davon abhängig ist. Da sich pos->sub auf root bezieht, muß pos->no++ das demnach auch.

2. Bei einem = wird immer erst der Teil rechts vom = ausgewertet, muß zumindest. Das Postinkrement steht rechts, also muß auch das Inkrement selbst ausgeführt werden, bevor die Neuzuweisung von pos erfolgt.

Ich halte das recht sicher für einen Compilerfehler.

Xmas
2006-03-18, 14:43:33
2. Bei einem = wird immer erst der Teil rechts vom = ausgewertet, muß zumindest. Das Postinkrement steht rechts, also muß auch das Inkrement selbst ausgeführt werden, bevor die Neuzuweisung von pos erfolgt.
Laut C++-Standard eben nicht. Dabei wäre genau das die einzig sinnvolle Auswertungsreihenfolge.
pos=&pos->sub[pos->no++];

int postinkrement(int& i)
{
int ret = i;
i += 1;
return ret;
}
pos = &pos->sub[postinkrement(pos->no)];


Aber rate mal was VC2005 daraus macht:
int i = 0;
i = i++;

Coda
2006-03-18, 14:50:27
Dieses seltsame Verhalten kommt aber noch aus C-Tagen, dafür kann C++ nix.

Neomi
2006-03-18, 15:06:56
Laut C++-Standard eben nicht. Dabei wäre genau das die einzig sinnvolle Auswertungsreihenfolge.

Hmmm, das ist irgendwie sinnlos. Ist das überhaupt irgendwie definiert oder steht das den Compilerbauern frei?

Aber rate mal was VC2005 daraus macht:
int i = 0;
i = i++;

Die sinnvolle Variante wäre 0, aber so ganz ohne feste Definition wird das wohl ja nach Compiler anders aussehen. Und bei manchen Compilern wird das bestimmt noch von den Optimierungen abhängen.

Coda
2006-03-18, 15:21:35
Hmmm, das ist irgendwie sinnlos. Ist das überhaupt irgendwie definiert oder steht das den Compilerbauern frei?Nein es ist eben nicht definiert. Ich denke das Ergebnis hängt vor allem vom verwendeten Parser ab - genau der hat sich nämlich geändert in GCC 4 X-D

Xmas
2006-03-18, 16:03:55
Dieses seltsame Verhalten kommt aber noch aus C-Tagen, dafür kann C++ nix.
Man hätte es ändern können. Etwas Undefiniertes zu definieren bringt schließlich keine Kompatibilitätsprobleme.

Die sinnvolle Variante wäre 0, aber so ganz ohne feste Definition wird das wohl ja nach Compiler anders aussehen. Und bei manchen Compilern wird das bestimmt noch von den Optimierungen abhängen.
VC2005 macht 1 daraus.

SimonX
2007-04-17, 12:52:09
So ein ähnliche Situation wurde in 4.1.2 gefixed.

http://gcc.gnu.org/bugzilla/show_bug.cgi?id=29154