9
votes

Comment Malloc () peut-il causer un SIGSEGV?

J'ai un bug étrange dans mon programme, il me semble que MALLOC () causait un SIGSEGV, qui, aussi loin que mon compréhension, ne donne aucun sens. J'utilise une bibliothèque appelée simClist pour des listes dynamiques.

Voici une struct qui est référencée ultérieurement: p> xxx pré>

et voici le code: p>

#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


1 commentaires

À titre de note latérale, appeler srandom () plus d'une fois n'est pas recommandé. Pour éviter les futurs bugs, même dans list_init () est connu pour être appelé une seule fois, vous devez déplacer cet ensemencement à un endroit qui est plus évidemment exécuté une fois comme le dessus de principal () .


6 Réponses :


27
votes

malloc peut segfault par exemple lorsque le tas est corrompu. Vérifiez que vous n'écrivez rien au-delà des limites d'une allocation précédente.


2 commentaires

Et utilisez Valgrind! D'autres affiches ont mentionné cet outil, mais malheureusement n'a pas eu beaucoup de upvotes. Rien de mal à cette réponse, mais toute discussion sur la corruption de la mémoire est incomplète sans un avertissement pour utiliser Valgrind!


Je recevais un SIGSEGV lorsque vous appelez gratuitement (). J'ai couru le code sous Valgrind et j'ai montré que j'avais écrit au-delà d'un tampon et corrompu le tas.



12
votes

Vous vous avez probablement corrompu, vous avez corrompu quelque part avant cet appel par un débordement de tampon ou en appelant gratuit avec un pointeur qui n'a pas été attribué par Malloc (ou c'était déjà libéré).

Si les structures de données internes utilisées par MALLOC sont corrompues de cette façon, MALLOC utilise des données non valides et pourrait se bloquer.


0 commentaires

17
votes

Une violation probablement de la mémoire se produit dans une autre partie de votre code. Si vous êtes sur Linux, vous devez absolument essayer Valgrind. Je ne ferais jamais confiance à mes propres programmes C à moins qu'il ne passe Valgrind.

Edit: Un autre outil utile est clôture électrique . Glibc fournit également le Malloc_Check_ variable environnementale pour aider à déboguer des problèmes de mémoire. Ces deux méthodes n'affectent pas la vitesse de fonctionnement autant que Valgrind.


0 commentaires

2
votes

Vous devriez essayer de déboguer ce code dans l'isolement, pour voir si le problème est réellement situé là où le SEGFAULT est généré. (Je soupçonne que ce n'est pas).

Cela signifie:

# 1: compilez le code avec -O0 pour vous assurer que GDB reçoit des informations de numérotation de ligne correctes.

# 2: Écrivez un test d'unité qui appelle cette partie du code.

Je suppose que le code fonctionnera correctement lorsqu'il sera utilisé séparément. Vous pouvez ensuite tester vos autres modules de la même manière, jusqu'à ce que vous découvriez ce qui provoque le bogue.

Utiliser Valgrind, comme d'autres ont suggéré, c'est aussi une très bonne idée.


0 commentaires

4
votes

Il y a une myriade de méthodes de déclenchement d'un vidage de base de MALLOC () (et realloc () et calloc () ). Ceux-ci incluent:

  • Dépassement de la mémoire tampon: écriture au-delà de la fin de l'espace alloué (informations de contrôle du piétinement que MALLOC () était en train de rester là).
  • BUFFER BUFFER: Écriture avant le début de l'espace alloué (informations de contrôle du piétinement que MALLOC () était en train de rester là).
  • libérant la mémoire qui n'a pas été attribuée par masloc () . Dans un programme mixte C et C ++, cela inclurait libérer la mémoire allouée en C ++ par nouveau .
  • libérant un pointeur qui pointe une partie à travers un bloc de mémoire alloué par MALLOC () - qui est un cas particulier de l'espèce précédent.
  • libérant un pointeur déjà libéré - le notoire "double libre".

    Utilisation d'une version de diagnostic de MALLOC () ou activant les diagnostics de la version standard de votre système, peut aider à identifier certains de ces problèmes. Par exemple, il peut être capable de détecter de petits métro et des débordements (car il alloue un espace supplémentaire pour fournir une zone tampon autour de l'espace que vous avez demandé), et il peut probablement détecter les tentatives de mémoire libre qui n'a pas été attribuée ou qui était déjà libérée. ou des pointeurs faisant partie de l'espace alloué - car il stockera les informations séparément de l'espace alloué. Le coût est que la version de débogage prend plus d'espace. Un très bon allocator pourra enregistrer les numéros de trace de la pile et les numéros de ligne pour vous indiquer où l'allocation s'est produite dans votre code ou où le premier libre est survenu.


0 commentaires

0
votes

Le code est problématique. Si MALLOC renvoie NULL, cette affaire n'est pas traitée correctement dans votre code. Vous supposez simplement que la mémoire a été allouée pour vous quand elle n'a pas été. Cela peut provoquer une corruption de mémoire.


0 commentaires