Valgrind: lecture invalide de taille 4 -> sigsegv, fonctionne très bien sans valgrind et dans Visual Studio

J’ai implémenté un algorithme de compression (utilisant le codage huffman) qui utilise une queue prioritaire de noeuds (une structure définie). Maintenant, quand je viens de lancer le code sous Linux ou dans Visual Studio, tout fonctionne bien. Lorsque je vérifie les memory leaks dans Visual Studio, aucune information n’est fournie.

Le problème est maintenant, lorsque j’utilise valgrind pour parsingr mon programme, il se termine par le signal 11 (sigsegv). La première erreur rencontrée est une “lecture invalide de taille 4” dans la méthode delete min. Les autres erreurs suivantes sont les suivantes: adresse: 0 octet dans un bloc de taille 453 libérée, écriture non valide de taille 4, libre non valide, suppression ou realloc.

Quelqu’un peut-il me donner des conseils sur le type d’erreur que j’aurais pu éventuellement commettre? Cela fait des heures que je fais des recherches sur Internet, mais je ne trouve pas ce que je fais de mal (d’autant plus que cela fonctionne sans utiliser valgrind). Ou des astuces pour déboguer et découvrir la cause de l’erreur de lecture.

Merci beaucoup!

Voici le code au cas où quelqu’un voudrait le réviser, mais je suppose que ce n’est pas si facile de plonger dans ce code spécifique.

Je suppose que cela a quelque chose à voir avec la queue prioritaire du code:

La partie où je fais la partie huffman -> à chaque fois, supprime les 2 nœuds minimaux et ajoute la sum des deux en un seul nœud.

while(queue->size > 1){ node* n1 = delete_min(queue); node* n2 = delete_min(queue); // all the errors are encountered in this call node* temp = (node*) calloc(sizeof(node),1); temp->amount = n1->amount + n2->amount; insert_node(queue,temp); n1->parent = temp; n2->parent = temp; temp->left = n1; temp->right = n2; } 

Voici les méthodes delete_min et insert_node pour la queue prioritaire:

 void insert_node(priority_queue* p_queue, node* x){ int i = p_queue->size; if(i == 0){ p_queue->queue = (node**) malloc(sizeof(node*)); } else{ p_queue->queue = (node**) realloc(p_queue->queue,sizeof(node*)*(p_queue->size+1)); } p_queue->queue[p_queue->size] = x; while(i>=0 && p_queue->queue[i]->amount 

queue[(i-1)/2]->amount){ node* temp = p_queue->queue[i]; p_queue->queue[i] = p_queue->queue[(i-1)/2]; p_queue->queue[(i-1)/2] = temp; i = (i-1)/2; } p_queue->size++; } node* delete_min(priority_queue* p_queue){ node** queue = p_queue->queue; node* min = queue[0]; if(p_queue->size>1){ int r = 0; int current = 1; //left child of root queue[0] = queue[p_queue->size-1]; queue = (node**) realloc(queue,sizeof(node*)*(--p_queue->size)); while(current

size){ //in case of 2 children, check if current needs to be right or left child if(current

size-1 && queue[current] > queue[current+1]){ current++; } if(queue[current] size--; } return min; }

EDIT: Ajout de la sortie valgrind:

 Invalid read of size 4 ==1893== at 0x80498E0: delete_min (huffman.c:331) ==1893== by 0x80492DA: huffman_encode (huffman.c:196) ==1893== by 0x8049DDE: encode_file (main.c:94) ==1893== by 0x8049BBE: main (main.c:32) ==1893== Address 0x441d9a8 is 0 bytes inside a block of size 452 free'd ==1893== at 0x402BC70: realloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==1893== by 0x8049922: delete_min (huffman.c:335) ==1893== by 0x80492CC: huffman_encode (huffman.c:195) ==1893== by 0x8049DDE: encode_file (main.c:94) ==1893== by 0x8049BBE: main (main.c:32) ==1893== ==1893== Invalid read of size 4 ==1893== at 0x8049901: delete_min (huffman.c:333) ==1893== by 0x80492DA: huffman_encode (huffman.c:196) ==1893== by 0x8049DDE: encode_file (main.c:94) ==1893== by 0x8049BBE: main (main.c:32) ==1893== Address 0x441db64 is 444 bytes inside a block of size 452 free'd ==1893== at 0x402BC70: realloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==1893== by 0x8049922: delete_min (huffman.c:335) ==1893== by 0x80492CC: huffman_encode (huffman.c:195) ==1893== by 0x8049DDE: encode_file (main.c:94) ==1893== by 0x8049BBE: main (main.c:32) ==1893== ==1893== Invalid write of size 4 ==1893== at 0x8049906: delete_min (huffman.c:333) ==1893== by 0x80492DA: huffman_encode (huffman.c:196) ==1893== by 0x8049DDE: encode_file (main.c:94) ==1893== by 0x8049BBE: main (main.c:32) ==1893== Address 0x441d9a8 is 0 bytes inside a block of size 452 free'd ==1893== at 0x402BC70: realloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==1893== by 0x8049922: delete_min (huffman.c:335) ==1893== by 0x80492CC: huffman_encode (huffman.c:195) ==1893== by 0x8049DDE: encode_file (main.c:94) ==1893== by 0x8049BBE: main (main.c:32) ==1893== ==1893== Invalid free() / delete / delete[] / realloc() ==1893== at 0x402BC70: realloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==1893== by 0x8049922: delete_min (huffman.c:335) ==1893== by 0x80492DA: huffman_encode (huffman.c:196) ==1893== by 0x8049DDE: encode_file (main.c:94) ==1893== by 0x8049BBE: main (main.c:32) ==1893== Address 0x441d9a8 is 0 bytes inside a block of size 452 free'd ==1893== at 0x402BC70: realloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==1893== by 0x8049922: delete_min (huffman.c:335) ==1893== by 0x80492CC: huffman_encode (huffman.c:195) ==1893== by 0x8049DDE: encode_file (main.c:94) ==1893== by 0x8049BBE: main (main.c:32) ==1893== ==1893== Invalid read of size 4 ==1893== at 0x8049A0E: delete_min (huffman.c:337) ==1893== by 0x80492DA: huffman_encode (huffman.c:196) ==1893== by 0x8049DDE: encode_file (main.c:94) ==1893== by 0x8049BBE: main (main.c:32) ==1893== Address 0x0 is not stack'd, malloc'd or (recently) free'd ==1893== ==1893== ==1893== Process terminating with default action of signal 11 (SIGSEGV) ==1893== Access not within mapped region at address 0x0 ==1893== at 0x8049A0E: delete_min (huffman.c:337) ==1893== by 0x80492DA: huffman_encode (huffman.c:196) ==1893== by 0x8049DDE: encode_file (main.c:94) ==1893== by 0x8049BBE: main (main.c:32) 

La ligne 331 est la ligne dans delete_min de: noeud * min = queue [0];

MODIFIER:

Le problème est résolu maintenant. Dans la réponse acceptée, la raison en est expliquée. En affectant correctement la valeur réaffectée, dans delete_min, tous les problèmes ont été résolus.

 //realloc queue and assign new value to local queue var p_queue->queue = (node**) realloc(queue,sizeof(node*)*(--p_queue->grootte)); queue = p_queue->queue; 

Je vais vous expliquer la première erreur.

 ==1893== Invalid read of size 4 ==1893== at 0x80498E0: delete_min (huffman.c:331) ==1893== by 0x80492DA: huffman_encode (huffman.c:196) ==1893== by 0x8049DDE: encode_file (main.c:94) ==1893== by 0x8049BBE: main (main.c:32) 

À la ligne 331, vous lisez probablement un int (non signé), dans une partie de la mémoire que vous n’avez pas allouée pour votre propre programme.

 ==1893== Address 0x441d9a8 is 0 bytes inside a block of size 452 free'd ==1893== at 0x402BC70: realloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so) ==1893== by 0x8049922: delete_min (huffman.c:335) ==1893== by 0x80492CC: huffman_encode (huffman.c:195) ==1893== by 0x8049DDE: encode_file (main.c:94) ==1893== by 0x8049BBE: main (main.c:32) ==1893== 

Cette partie donne plus d’informations sur la partie de la mémoire que vous avez essayé de lire. Il dit que vous avez déjà utilisé la mémoire, mais que reallox l’a libérée. Cela signifie que vous lisez un ancien pointeur sur une partie de la mémoire que vous avez reconstituée.

Vous devez vous assurer que vous utilisez le pointeur realloc, et non l’ancien.

La raison pour laquelle cela ne plante pas en dehors de valgrind, c’est que la plupart du temps, la même partie de la mémoire est allouée par realloc. Le pointeur rest donc le même et votre code fonctionnera comme tel. Cependant, parfois, realloc décidera de déplacer la partie de la mémoire et votre code plantera. Valgrind essaie de te prévenir.

Le rest des erreurs sera probablement résolu lorsque vous utilisez le pointeur renvoyé.

Selon vos erreurs Valgrind, vous accédez probablement à des nœuds déjà supprimés, puis vous les libérez. Vous devez envisager de publier les erreurs Valgrind avec les numéros de ligne correspondants (à comstackr avec -g dans gcc) afin de nous permettre de vous aider plus facilement.

Edit: L’erreur la plus flagrante, la erreur de segmentation, est l’endroit où vous devez commencer le débogage. Cette ligne échoue:

 while((2*i)+2 < p_queue->grootte-1 && (queue[i]->amount > queue[(2*i)+1]->amount || queue[i]->amount > queue[(2*i)+2]->amount)){ 

probablement parce que la queue est NULL. Pourquoi est-il nul? Probablement parce que realloc n’a rien alloué. Pourquoi n’a-t-il rien alloué? Soit parce que vous avez manqué de mémoire (peu probable), soit parce que vous avez essayé d’allouer un object de taille 0. (Voir http://www.cplusplus.com/reference/cstdlib/realloc/ pour plus de détails sur realloc) Comment pouvez-vous demander la taille 0? Si p_queue->size-1 est 0.