Wie kann malloc () einen SIGSEGV verursachen?

8

Ich habe einen seltsamen Fehler in meinem Programm, es scheint mir, dass malloc () einen SIGSEGV verursacht, was nach meinem Verständnis keinen Sinn ergibt. Ich verwende eine Bibliothek namens Simclist für dynamische Listen.

Hier ist eine Struktur, auf die später verwiesen wird:

%Vor%

Und hier ist der Code:

%Vor%

list_init ist der Ort, an dem das Programm fehlschlägt, hier ist der Code für list_init:

%Vor%

Die Zeile l->spareels = (struct list_entry_s **)malloc(SIMCLIST_MAX_SPARE_ELEMS * ist die Stelle, an der SIGSEGV entsprechend der Stack-Trace verursacht wird. Ich benutze gdb / nemiver zum Debuggen, bin aber ratlos. Wenn diese Funktion das erste Mal aufgerufen wird, funktioniert sie einwandfrei, aber beim zweiten Mal schlägt sie immer fehl. Wie kann malloc () eine SIGSEGV verursachen?

Dies ist der Stack-Trace:

%Vor%

Jede Hilfe oder Einsicht wird sehr geschätzt!

    
user19745 17.09.2009, 19:59
quelle

6 Antworten

25

malloc kann beispielsweise segfault sein, wenn der Heap beschädigt ist. Überprüfen Sie, dass Sie nichts über die Grenzen einer früheren Zuweisung hinaus schreiben.

    
laalto 17.09.2009, 20:07
quelle
16

Wahrscheinlich tritt in anderen Teilen Ihres Codes eine Speicherverletzung auf. Wenn Sie unter Linux sind, sollten Sie Valgrind auf jeden Fall ausprobieren. Ich würde meinen eigenen C-Programmen niemals trauen, wenn sie Valgrind nicht bestehen.

EDIT: Ein weiteres nützliches Werkzeug ist Elektrozaun . Glibc bietet außerdem die Umgebungsvariable MALLOC_CHECK_ , um Speicherprobleme zu beheben. Diese beiden Methoden beeinflussen die Laufgeschwindigkeit nicht so sehr wie Valgrind.

    
user172818 17.09.2009 20:10
quelle
12

Wahrscheinlich haben Sie vor dem Aufruf durch einen Pufferüberlauf oder durch den Aufruf von free mit einem Zeiger, der nicht von malloc zugewiesen wurde (oder der bereits freigegeben wurde), einen Heapspeicher erstellt.

Wenn die von malloc verwendeten internen Datenstrukturen auf diese Weise beschädigt werden, verwendet malloc ungültige Daten und stürzt möglicherweise ab.

    
sth 17.09.2009 20:07
quelle
4

Es gibt unzählige Möglichkeiten, einen Core-Dump von malloc() (und realloc() und calloc() ) auszulösen. Dazu gehören:

  • Pufferüberlauf: Schreiben über das Ende des zugewiesenen Speicherplatzes hinaus (Trampling-Steuerinformationen, die malloc() dort behalten hat).
  • Pufferunterlauf: Schreiben vor dem Start des zugewiesenen Speicherplatzes (Trampling-Steuerinformationen, die malloc() dort behalten hat).
  • Freigeben von Speicher, der nicht von malloc() zugewiesen wurde. In einem gemischten C- und C ++ - Programm würde das das Freigeben von Speicher umfassen, der in C ++ von new zugeordnet wurde.
  • Freigeben eines Zeigers, der teilweise durch einen Speicherblock zeigt, der von malloc() zugewiesen wurde - was ein Spezialfall des vorherigen Falls ist.
  • Freigeben eines bereits freigegebenen Zeigers - das berüchtigte "Double Free".

Die Verwendung einer Diagnoseversion von malloc() oder das Aktivieren der Diagnose in der Standardversion Ihres Systems kann dabei helfen, einige dieser Probleme zu identifizieren. Beispielsweise kann es kleine Unterläufe und Überläufe erkennen (da es zusätzlichen Speicherplatz reserviert, um eine Pufferzone um den angeforderten Speicherplatz bereitzustellen), und es kann Versuche zum Freigeben von Arbeitsspeicher, der nicht zugewiesen wurde oder der bereits freigegeben wurde, erkennen oder Zeiger teilweise durch den zugewiesenen Speicherplatz - weil es die Informationen getrennt von dem zugewiesenen Speicherplatz speichert. Die Kosten liegen darin, dass die Debugging-Version mehr Speicherplatz benötigt. Ein wirklich guter Allokator ist in der Lage, die Stack-Trace- und Zeilennummern aufzuzeichnen, um Ihnen mitzuteilen, wo die Zuordnung in Ihrem Code stattgefunden hat oder wo der erste freie Code aufgetreten ist.

    
Jonathan Leffler 17.09.2009 20:19
quelle
1

Sie sollten versuchen, diesen Code isoliert zu debuggen, um festzustellen, ob das Problem tatsächlich dort liegt, wo der Segfault generiert wird. (Ich vermute, dass es nicht ist).

Dies bedeutet:

# 1: Kompilieren Sie den Code mit -O0, um sicherzustellen, dass gdb korrekte Zeilennummerierungsinformationen erhält.

# 2: Schreiben Sie einen Komponententest, der diesen Teil des Codes aufruft.

Ich schätze, dass der Code bei separater Verwendung korrekt funktioniert. Sie können dann Ihre anderen Module auf die gleiche Weise testen, bis Sie herausfinden, was den Fehler verursacht.

Valgrind zu verwenden, wie andere vorgeschlagen haben, ist auch eine sehr gute Idee.

    
Jørgen Fogh 17.09.2009 20:17
quelle
0

Der Code ist problematisch. Wenn malloc NULL zurückgibt, wird dieser Fall in Ihrem Code nicht korrekt behandelt. Sie nehmen einfach an, dass Speicher für Sie reserviert wurde, obwohl dies nicht der Fall war. Dies kann Speicherbeschädigung verursachen.

    
steve 27.09.2009 09:12
quelle

Tags und Links