Hallo,
ich habe ein Programm, das in folgender Zeile einen Segfault produziert:
unsigned char *srcsrc; srcsrc = (unsigned char*) malloc (i * sizeof(unsigned char));
Das ganze ist unabh. von i; i kann dabei 1,2,3,...,$großeZahl sein.
Im gdb sieht das dann so aus:
(gdb) run Starting program: /path/prog
Program received signal SIGSEGV, Segmentation fault. 0x0000000000400ee8 in prog ( parameter1=0x7ffff783a010 parameter2=... at prog.c:107 107 srcsrc = (unsigned char*) malloc (i * sizeof(unsigned char)); (gdb) print i $1 = 1
*Irgendwie* scheint es eine Abhängigkeit zu den Daten zu geben, mit denen ich das Programm füttere (das habe ich hier minimiert, indem ich immer gleich viel Speicher allokiere und außer der gezeigten Allokation nichst in dieser Funktion mache).
Ich kann mir gar keinen Reim darauf machen, wie ein malloc überhaupt fehlschlagen kann (und entsprechend nicht, wo ich nach dem Problem suchen muss).
Hat jemand eine Idee, woran das liegen könnte?
(freier RAM ist reichlich vorhanden, System ist Ubuntu 11.04 AMD64)
Viele Grüße Fabian
Hallo,
kleiner Nachtrag: Valgrind vermeldet das Folgende (was mir auch nicht weiterhilft):
==26537== Warning: client switching stacks? SP change: 0x7fefffed0 --> 0x7fdf931d0 ==26537== to suppress, use: --max-stackframe=17222912 or greater ==26537== Warning: client switching stacks? SP change: 0x7fdf931d0 --> 0x7fdd85820 ==26537== to suppress, use: --max-stackframe=2152880 or greater ==26537== Invalid write of size 8 ==26537== at 0x400EA4: func_with_malloc (prog.c:107) ==26537== by 0x4015B5: immediate_func (prog.c:294) ==26537== by 0x40171E: main (prog.c:332)
(der Lesbarkeit halber reformatiert)
Viele Grüße Fabian
Hallo,
Lösung gefunden: das malloc() selbst hat nur wenig mit dem segfault zu tun. Ursache ist ein voller Heap.
Ich hatte sinngemäß Folgendes:
void func_with_malloc(int length) { char data[length]; unsigned char *srcsrc;
srcsrc = (unsigned char*) malloc(length); }
Wenn nun length zu groß wurde, fühlte sich das anschließende malloc bedrängt.
Unklar ist mir, wieso ich in dem Fall nicht bei CALL einen Heap Overflow oder ähnliches gemeldet bekomme. Und bei length=1M sollte das Limit von 8M eigentlich auch noch ein Stückchen entfernt sein. Aber gut, das Problem ist gelöst.
Viele Grüße Fabian
Hallo Fabian,
Fabian Hänsel fabtagon@gmx.de:
Lösung gefunden: das malloc() selbst hat nur wenig mit dem segfault zu tun. Ursache ist ein voller Heap.
Ich hatte sinngemäß Folgendes:
void func_with_malloc(int length) { char data[length]; unsigned char *srcsrc;
srcsrc = (unsigned char*) malloc(length);
}
Wenn nun length zu groß wurde, fühlte sich das anschließende malloc bedrängt.
Unklar ist mir, wieso ich in dem Fall nicht bei CALL einen Heap Overflow oder ähnliches gemeldet bekomme.
Weil vor dem malloc() noch keine Schreiboperationen im Speicher erfolgen. Die Definition von data[] setzt erstmal bloss den Stackpointer deutlich nach unten. Erst das Schreiben des Arguments zu malloc() oder der Ruecksprung- Adresse (je nach Call-Konvention) in den Stack zeigt das Problem.
Holger
On Monday 09 May 2011 08:02:40 holger.dietze@arcor.de wrote:
Fabian Hänsel fabtagon@gmx.de:
Lösung gefunden: das malloc() selbst hat nur wenig mit dem segfault zu tun. Ursache ist ein voller Heap.
Ich hatte sinngemäß Folgendes: void func_with_malloc(int length) {
char data[length]; unsigned char *srcsrc; srcsrc = (unsigned char*) malloc(length);
}
Wenn nun length zu groß wurde, fühlte sich das anschließende malloc bedrängt.
Unklar ist mir, wieso ich in dem Fall nicht bei CALL einen Heap Overflow oder ähnliches gemeldet bekomme.
Weil vor dem malloc() noch keine Schreiboperationen im Speicher erfolgen. Die Definition von data[] setzt erstmal bloss den Stackpointer deutlich nach unten. Erst das Schreiben des Arguments zu malloc() oder der Ruecksprung- Adresse (je nach Call-Konvention) in den Stack zeigt das Problem.
Guter Einwurf! Ich hatte die dynamische Stack-Allocation nicht gesehen.
Es ist im Allgemeinen keine gute Idee sehr grosse Datenblöcke auf dem Stack abzulegen. Ein wenig googeln sagt uns, dass das Stack-Segment eines Thread zw. 8 und 10MB groß werden darf - normalerweise ist das jenseits alles Notwendigen, aber Dein Code kann das locker überspringen. Bei embedded Systemen kann die erlaubte Stackgröße sogar darunter liegen (ich habe schon Werte von 32kB in freier Wildbahn gesehen).
Kleiner Hinweis: mit GNU LibC ist jedes Programm ein multi-thread Programm. Spätestens, wenn Du nach einer IP-Adresse fragst macht die Libc einen Helper- Thread auf.
Wenn Du C++ verwendest kannst Du das Problem sehr leicht umgehen, indem Du Dir eine Array-Klasse schreibst, die die eigentlichen Daten auf den Heap legt. (QByteArray und QString aus Qt machen das so.)
Konrad
Hej Holger!
2011-05-09 08:02, holger.dietze@arcor.de skrev:
Unklar ist mir, wieso ich in dem Fall nicht bei CALL einen Heap Overflow oder ähnliches gemeldet bekomme.
Weil vor dem malloc() noch keine Schreiboperationen im Speicher erfolgen. Die Definition von data[] setzt erstmal bloss den Stackpointer deutlich nach unten. Erst das Schreiben des Arguments zu malloc() oder der Ruecksprung- Adresse (je nach Call-Konvention) in den Stack zeigt das Problem.
Ah, das erklärt auch, warum das Problem sogar dann auftrat, wenn ich statt srcsrc = malloc(..) nur malloc() verwendet habe (und also gar keine meiner Daten auf dem Stack landen).
Danke euch beiden & Viele Grüße Fabian (der nie wieder um sich Pointer zu ersparen der Einfachheit halber den Heap zumüllen wird)
On Monday 09 May 2011 12:05:29 Fabian Hänsel wrote:
Ah, das erklärt auch, warum das Problem sogar dann auftrat, wenn ich statt srcsrc = malloc(..) nur malloc() verwendet habe (und also gar keine meiner Daten auf dem Stack landen).
Danke euch beiden & Viele Grüße Fabian (der nie wieder um sich Pointer zu ersparen der Einfachheit halber den Heap zumüllen wird)
Ich glaube Du hast hier gerade Stack und Heap verwechselt:
Stack ist das wo lokale Variablen landen. Heap ist das wo globale Variablen sind und wo malloc und new Daten hinlegen.
Beispiel:
int ich_bin_auf_dem_heap_und_global;
void funktion() { int ich_bin_auf_dem_stack; char *ich_zeige_auf_den_heap = malloc(1024); int *ich_zeige_auf_den_stack = &ich_bin_auf_dem_stack; /* nicht vergessen: */ free(ich_zeige_auf_den_heap); }
void absturz() { int hmm; int ich_bin_zu_gross[11*1024*1024]; int buuh; /*je nach Speicherlayout verursacht einer von beiden den Absturz:*/ hmm=buuh=1;/*SIGSEGV*/ }
int main() { int ich_bin_auch_auf_dem_stack; funktion(); absturz(); return 0; }
Konrad
2011-05-09 13:45, Konrad Rosenbaum skrev:
On Monday 09 May 2011 12:05:29 Fabian Hänsel wrote:
Ah, das erklärt auch, warum das Problem sogar dann auftrat, wenn ich statt srcsrc = malloc(..) nur malloc() verwendet habe (und also gar keine meiner Daten auf dem Stack landen).
Danke euch beiden& Viele Grüße Fabian (der nie wieder um sich Pointer zu ersparen der Einfachheit halber den Heap zumüllen wird)
Ich glaube Du hast hier gerade Stack und Heap verwechselt:
Oh ja, stimmt. Danke dir!
Viele Grüße Fabian
lug-dd@mailman.schlittermann.de