Wie kann malloc() bewirken, dass ein SIGSEGV?
Habe ich einen seltsamen bug in meinem Programm, es scheint mir, dass malloc() ist, dass eine SIGSEGV, soweit mein Verständnis geht, macht keinen Sinn. Ich bin mit einer Bibliothek namens simclist für dynamische Listen.
Hier ist eine Struktur, die später verwiesen wird:
typedef struct {
int msgid;
int status;
void* udata;
list_t queue;
} msg_t;
Und hier ist der code:
msg_t* msg = (msg_t*) malloc( sizeof( msg_t ) );
msg->msgid = msgid;
msg->status = MSG_STAT_NEW;
msg->udata = udata;
list_init( &msg->queue );
list_init
ist, wo das Programm scheitert, hier ist der code für list_init:
/* list initialization */
int list_init(list_t *restrict l) {
if (l == NULL) return -1;
srandom((unsigned long)time(NULL));
l->numels = 0;
/* head/tail sentinels and mid pointer */
l->head_sentinel = (struct list_entry_s *)malloc(sizeof(struct list_entry_s));
l->tail_sentinel = (struct list_entry_s *)malloc(sizeof(struct list_entry_s));
l->head_sentinel->next = l->tail_sentinel;
l->tail_sentinel->prev = l->head_sentinel;
l->head_sentinel->prev = l->tail_sentinel->next = l->mid = NULL;
l->head_sentinel->data = l->tail_sentinel->data = NULL;
/* iteration attributes */
l->iter_active = 0;
l->iter_pos = 0;
l->iter_curentry = NULL;
/* free-list attributes */
l->spareels = (struct list_entry_s **)malloc(SIMCLIST_MAX_SPARE_ELEMS * sizeof(struct list_entry_s *));
l->spareelsnum = 0;
#ifdef SIMCLIST_WITH_THREADS
l->threadcount = 0;
#endif
list_attributes_setdefaults(l);
assert(list_repOk(l));
assert(list_attrOk(l));
return 0;
}
die Linie l->spareels = (struct list_entry_s **)malloc(SIMCLIST_MAX_SPARE_ELEMS *
ist, wo der SIGSEGV verursacht wird, nach dem stack-trace. Ich bin mit gdb/nemiver für das Debuggen, aber ich bin an einem Verlust. Das erste mal diese Funktion wird aufgerufen, es funktioniert gut, aber es schlägt immer fehl, das zweite mal. Wie kann malloc() bewirken, dass ein SIGSEGV?
Dies ist die Stapelüberwachung:
#0 ?? () at :0
#1 malloc () at :0
#2 list_init (l=0x104f290) at src/simclist.c:205
#3 msg_new (msg_switch=0x1050dc0, msgid=8, udata=0x0) at src/msg_switch.c:218
#4 exread (sockfd=8, conn_info=0x104e0e0) at src/zimr-proxy/main.c:504
#5 zfd_select (tv_sec=0) at src/zfildes.c:124
#6 main (argc=3, argv=0x7fffcabe44f8) at src/zimr-proxy/main.c:210
Jede Hilfe oder Einsicht wird sehr geschätzt!
- Wie ist
list_t
erklärt? - Als seitliche Anmerkung, die Berufung
srandom()
mehr als einmal ist nicht zu empfehlen. Zur Vermeidung künftiger Fehler auch inlist_init()
ist bekannt, die nur einmal aufgerufen werden, sollten Sie verschieben, dass das seeding an einen Ort, der mehr ist natürlich einmal ausgeführt, wie in der Nähe der Spitze dermain()
.
Du musst angemeldet sein, um einen Kommentar abzugeben.
malloc
können segfault zum Beispiel, wenn der heap beschädigt ist. Prüfen Sie, ob Sie nicht schriftlich alles, was über die Grenzen einer früheren Zuordnung.Wahrscheinlich speicherschutzverletzung Auftritt in den anderen Teil des Codes. Wenn Sie auf Linux sind, sollten Sie auf jeden Fall versuchen valgrind. Ich würde mich nie trauen meine eigenen C-Programmen, es sei denn, es geht valgrind.
EDIT: ein weiteres nützliches tool ist Electric fence. Glibc stellt auch die MALLOC_CHECK_ Umwelt-Variablen zum Debuggen von Speicherproblemen. Diese zwei Methoden keinen Einfluss auf das laufende Geschwindigkeit so viel wie valgrind.
Haben Sie wahrscheinlich beschädigt Sie heap irgendwo vor diesem Aufruf durch einen Pufferüberlauf oder telefonisch
free
mit einem Zeiger, der nicht zugeordnetmalloc
(oder die, die bereits freigegeben wurde).Wenn die internen Datenstrukturen verwendet, die durch malloc beschädigt diese Weise, malloc ist mit ungültigen Daten und Abstürzen.
Gibt es unzählige Möglichkeiten der Auslösung eines core-dump von
malloc()
(undrealloc()
undcalloc()
). Dazu gehören:malloc()
halten dort).malloc()
halten dort).malloc()
. In einer gemischten C-und C++ - Programm, das wäre auch die Freigabe von Speicher erfolgt in C++ durchnew
.malloc()
- das ist ein spezieller Fall der vorigen Fall.Mithilfe eines Diagnose-version von
malloc()
oder aktivieren der Diagnose in Ihrem system die standard-version, kann helfen, zu identifizieren, einige dieser Probleme. Zum Beispiel, es kann in der Lage sein zu erkennen, kleine unter-und überläufe (da er reserviert zusätzlichen Platz, um eine Puffer-zone um den Platz, den Sie angefordert), und es kann wohl erkennen versucht, Speicher freizugeben, der nicht reserviert wurde oder dass bereits freigegeben wurde oder der Zeiger einen Teil des Weges durch den zugewiesenen Platz - denn es wird speichern die Informationen, die separat von den zugewiesenen Raum. Die Kosten ist, dass die debugging-version mehr Platz in Anspruch nimmt. Ein wirklich gutes Zuweisung wird erfassen können, die stack-trace-und Zeilennummern zu sagen, wo die Zuteilung erfolgte in Ihrem code, oder wo die erste freie trat.Sollten Sie versuchen, um diesen code zu Debuggen, die in isolation, um zu sehen, ob das problem tatsächlich liegt, wo der segfault erzeugt wird. (Ich vermute, dass es das nicht ist).
Bedeutet dies:
#1: Kompilieren Sie den code mit -O0, um sicherzustellen, dass gdb bekommt richtige Zeilennummerierung Informationen.
#2: Schreiben Sie einen unit test, der fordert, diesen Teil des Codes.
Meine Vermutung ist, dass der code funktioniert korrekt, wenn Sie separat verwendet werden. Sie können dann testen Sie Ihre anderen Modulen in der gleichen Weise, bis Sie herausfinden, was bewirkt, dass der bug.
Verwendung von Valgrind, wie andere vorgeschlagen haben, ist auch eine sehr gute Idee.
Code ist problematisch. Wenn malloc NULL zurück, ist in diesem Fall nicht korrekt behandelt in Ihrem code. Sie einfach davon ausgehen, dass der Speicher reserviert wurde, für Sie, wenn Sie es tatsächlich nicht wurde. Dies kann eine Speicherbeschädigung verursachen.