PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Fehler in gcc oder Electric Fence?



nobody0
24-08-2003, 10:48
Beim Debugen ist mir aufgefallen, dass dieses minimale C-Programm



#include <assert.h>
#include <math.h>
#include <string.h>
#include <setjmp.h>
#include <stdio.h>
#include <sys/time.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <signal.h> // signals

int
main (int argc, char *argv[])
{
char line[100000][256] = { {'\0'} };
return (0);
}


korrekt läuft, wenn es ohne Electric Fence compiliert wird, aber mit Electric Fence, konkret

gcc -O3 -D__SMP__ -D_REENTRANT -lm -lz -Wall -pedantic -ggdb -lefence -o error0 error0.c

liefert es nur "Speicherzugriffsfehler".
Insight meldet nur "Cannot insert breakpoint 1:" und gdb meldet
"Warning:
Cannot insert breakpoint -2.
Error accessing memory address 0x4000bb50: Eingabe-/Ausgabefehler.
The same program may be running in another process. "

Ist das ein Fehler im gcc oder im Electric Fence? :confused:

wraith
24-08-2003, 11:08
Also an EFence kann es nicht liegen,weil EFence nur malloc/free und Co. überschreibt,also mit dynamischer Allokierung zutun hat.
Hier haben wir es aber mit dem Stack zu tun,und dein Beispiel Seg-fault bei mir auch (ohne EFence).Mach das Array kleiner,oder allokiere es zur Laufzeit,es ist zu groß für den Stack.

nobody0
24-08-2003, 14:50
Aha, aber standard-konform ist das nicht und merkwürdig ist ja, dass es ohne efence funktioniert. Mit 100.000 Zeilen von je 256 Zeichen habe ich es aber noch nicht getestet.

wraith
24-08-2003, 16:05
Original geschrieben von nobody0
Aha, aber standard-konform ist das nicht


Hmm?Was meinst du jetzt konkret damit?



und merkwürdig ist ja, dass es ohne efence funktioniert.
Glückssache würde ich sagen.
Auf drei getesteten Compilern schmiert dieser Code zur Laufzeit ab


int main() {
char line[100000][256];
}

außer,es ist die Optimierung nach ganz oben gedreht,und das Array wird wegoptimiert,dann nicht.
Naja,eine Warnung zur Compiletime wäre mir auch lieber.

nobody0
24-08-2003, 18:15
Original geschrieben von wraith
Hmm?Was meinst du jetzt konkret damit?


Ganz einfach: Wenn ich ein zweidimensionales Feld wie oben anlege, dann wird damit automatisch Speicher alloziert, so wie z. B. mittels
int i = 0;
(zumindest nach ANSI-C)! Und wenn alle Elemente mit einem Wert initialisiert werden, dann stehen n*m dieser Werte im Speicher; da gibt es keinen Grund abzuschmieren!

Wie mir nachträglich eingefallen ist, gab es mit dem gcc schon vor Jahren das Problem, dass Felder über 2 MB nicht oder nicht richtig angelegt wurden und es auch mit -Wall -pedantic nicht einmal eine Warnung gab! Bei einem 512 MB großen Feld war mir das aufgefallen und als Workaround um diesen Bug musste ich mit Pointern u. mit malloc arbeiten. Ich hatte das kurzzeitig vergessen, weil ich annahm, dass dieser Bug längst beseitigt ist, aber der ist ja immer noch drinn und auch immer ohne warning!!!
Da werde ich wohl einen Bug-Report schreiben müssen.

Dabei habe ich extra Felder fester Länge zur Limitierung verwendet um Fehler möglichst auszuschließen und nun muss ich wieder einen Workaround wegen diesem alten Compiler-Bug schreiben :(

wraith
24-08-2003, 18:41
Original geschrieben von nobody0
Ganz einfach: Wenn ich ein zweidimensionales Feld wie oben anlege, dann wird damit automatisch Speicher alloziert, so wie z. B. mittels
int i = 0;
(zumindest nach ANSI-C)! Und wenn alle Elemente mit einem Wert initialisiert werden, dann stehen n*m dieser Werte im Speicher; da gibt es keinen Grund abzuschmieren!
Ja,das hat mit Ansi C aber wenig bis nichts zutun,und ist auch kein Bug im gcc.
Es geht einfach um die Größe des Runtime-Stacks,die man auch mit irgendeiner Option erhöhen kann.
Es gibt keine Garantie,daß ein Feld von beliebiger Größe auf dem Stack Platz findet (im Standard gibt es den Begriff Stack nichtmal),genauso wenig wie es eine Garantie gibt,daß man ein dynamisches Feld beliebiger Größe auf dem Heap erstellen kann (auch einen Heap gibt es nicht im Standard).
Das ist alles abhängig vom OS und vom Compiler,darum hab' ich auch deinen Einwand mit standard konform nicht verstanden.



wegen diesem alten Compiler-Bug

Nochmal,es ist kein Compiler Bug,wie oben geschrieben,hab' ich es auf drei Compilern getestet (aktuellen != gcc Compilern),die werden wohl nicht alle den selben Bug haben ;).

Edit:Mit ulimit -a kannst du sehen,wie groß der Stack ist.

nobody0
24-08-2003, 20:38
Naja, es sollte aber zumindest eine Warnung geben, denn ulimit -a zeigt mir unlimited bei stack size, aber praktisch ist es winzig, gemessen an den 2 GB RAM. Und mit malloc u. Pointer funktionert es ja; den Bug gäbe es nicht, wenn arrays damit realisiert wären!
Gibt es denn keine libraries, die genau das machen? :confused:

wraith
24-08-2003, 21:07
Warum willst du überhaupt soviel Speicher auf dem Stack allokieren?


Original geschrieben von nobody0

Gibt es denn keine libraries, die genau das machen? :confused:
Wenn du auch C++ in Betracht ziehst,dann gibt es genug Möglichkeiten.
Ein std::vector macht genau das was du willst.
Wenn du bei C bleiben willst,dann mußt du ebend mit malloc selber ran.Ist ja keine große Sache,nur das Aufräumen nachher nicht vergessen.

Du könntest das Array auch static deklarrieren,aber dann bleibt der Speicher auch noch nach dem Funktionsaufruf erhalten.

nobody0
24-08-2003, 21:59
Aha, mit static funktioniert es; zumindest meldet efence nun nichts mehr.
Wieso funktioniert es denn mit static und ohne nicht? :confused: