Avoir du mal à suivre la corruption de mémoire – lors de l’exécution avec Valgrind, il s’exécute correctement sans erreur

Nous avons un programme complexe qui fonctionne bien avec les entrées lourdes (toute entrée en fait) sans multithreading mis en œuvre.
Nous avons implémenté le multithreading avec un pool de threads et, étant donné ces parameters d’entrée, j’obtiens ces résultats:
( Remarque : là où je dis pas d’erreur , cela signifie que j’ai testé avec valgrind -v et quand je dis pas de memory leaks , cela signifie que je l’ai testé avec valgrind --leak-check=full -v ).

  1. small_file: fonctionne avec plus de 1 travailleurs (threads), pas d’erreur Valgrind, pas de fuite de mémoire
  2. medium_file: Avec 1 travailleur, il s’exécute correctement, aucune erreur / fuite de mémoire. Avec> 1 ouvriers, je reçois: a. généralement une erreur de corruption de segment de mémoire, b. double libre. Lorsque vous exécutez valgrind -v avec plus d’un travailleur, le programme aboutit. De plus, aucune erreur n’est imprimée à partir de valgrind, c’est-à-dire ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 2 from 2) .

Maintenant que je ne reçois aucune erreur de valgrind, que puis-je faire pour résoudre le problème de corruption de mémoire dans cette application complexe et volumineuse?

Environnement de développement:
Ubuntu, 64 bits, version gcc: 4.7.2 et 4.8.1 (ordinateurs différents, version plus récente d’Ubuntu).

Avec> 1 ouvriers, je reçois: a. généralement une erreur de corruption de segment, b.double-free. Lorsque vous exécutez valgrind -v avec plus d’un travailleur, le programme aboutit

D’après les symptômes ci-dessus, il me semble qu’il y a clairement une sorte de problème de synchronisation dans votre programme. Il semble que votre programme partage l’adresse de mémoire de tas entre les threads et donc chaque fois qu’il y a une course de données que vous rencontrez un problème.

Vous avez également mentionné que lorsque vous exécutez valgrind -v, votre programme se termine avec succès. Cela indique que votre programme a un problème de synchronisation et qu’il dépend aussi de la séquence / du minutage. C’est l’un des bogues les plus difficiles à découvrir. Nous devons également nous rappeler que les outils dynamics ne donneraient aucun avertissement tant que le programme n’exécutera pas l’opération. Je veux dire qu’il pourrait y avoir un problème dans le programme, mais la séquence d’exécution (car il y a un problème lié au timing) a déterminé si les outils captureraient ces échecs ou non.

Ceci dit, je pense qu’il n’existe pas de moyen efficace de trouver de tels bugs dans les gros programmes. Cependant, je soupçonne fortement qu’il existe un scénario de course de données qui mène à une corruption de mémoire / une double libération. Vous pouvez donc utiliser Helgrind pour rechercher / identifier un problème d’exécution / de thread de données susceptible de provoquer une corruption de la mémoire.

Maintenant que je ne reçois aucune erreur de valgrind, que puis-je faire pour résoudre le problème de corruption de mémoire dans cette application complexe et volumineuse?

Eh bien, laissez-moi vous décrire ce que j’ai fait pour trouver des memory leaks dans l’implémentation de JavaScript par Microsoft dans les années 1990.

Je me suis d’abord assuré que, dans la version de débogage de mon programme, autant d’allocations de mémoire que possible étaient routées vers les mêmes méthodes d’assistance. C’est-à-dire que j’ai redéfini malloc , new , etc., pour qu’ils soient tous synonymes d’un allocateur que j’ai écrit moi-même.

Cet allocateur n’était qu’un mince shell autour d’un allocateur de mémoire de tas virtuel du système d’exploitation, mais il possédait quelques atouts supplémentaires. Il a alloué de la mémoire supplémentaire au début et à la fin du bloc et l’a remplie de valeurs sentinelles, d’un compte threadsafe du nombre d’allocations jusqu’à présent et d’une liste doublement sécurisée de toutes les allocations. La routine “libre” vérifierait que les valeurs sentinelles des deux côtés sont toujours intactes; sinon, il y a une corruption de mémoire quelque part. Cela dissocierait le bloc de la liste liée et le libérerait.

Je pouvais à tout moment demander au gestionnaire de mémoire une liste de tous les blocs en attente dans la mémoire, dans l’ordre dans lequel ils avaient été alloués. Les éléments laissés dans la liste lors du déchargement de la DLL étaient des memory leaks.

Ces outils m’ont permis de trouver très facilement des memory leaks et des corruptions de mémoire en temps réel.

Veuillez utiliser CORE DUMP :: [principalement utilisé dans les erreurs de type détectées par glibc à double libération]

Comstackz votre programme avec l’option gcc -g pour les informations de débogage

ulimit -a

il vous montrera la taille du fichier core

ulimit -c illimité

il va définir la taille du fichier de base illimité

Maintenant, lancez votre programme, puis dans votre répertoire courant un fichier va générer nommé “core”

puis parsingz-le par GDB comme ci-dessous ..

gdb ./votre programme

gdb) bt

il va vous montrer où est le problème ..

si vous rencontrez des difficultés, écrivez-moi …