在链表中使用 free() 的 Valgrind 错误
Valgrind errors for using free() in a linked list
我正在使用哈希数组制作一个项目。我正在放一张我在网上找到的图片,向你们展示我正在尝试做什么。 image
所以我在main中像这样初始化了左边的大数组:
cellule_t * array[HASH_MAX] = {NULL};
然后我完成了所有插入以创建链表。我现在想做的是释放()所有分配给创建这一切的内存。所以,就像我没有为大数组使用 malloc 一样,我只需要释放链表并且我正在使用这个函数:
但是我从 Valgrind 得到了一些错误并且块没有被释放。
我将我使用的所有功能(包括主要功能)放在一起,以使其更加清晰。
typedef struct cell{
char *mot;
char *traduction;
struct cell *suivant;
}cellule_t;
int main()
{
int indice;
cellule_t *cel;
FILE*file = NULL;
char buffer[100] = "hello bye glass sorry";
cellule_t *tabMajeur[HASH_MAX] = {0};
file = fopen("fichier.txt","r");
remplissage_hachage(tabMajeur,file); (c:157)
affichageTraduction(tabMajeur,buffer);
libererMemorie(tabMajeur); (c:159)
}
void remplissage_hachage (cellule_t **tabMajeur,FILE *fichier)
{
char string1[20];
unsigned int indice = 0;
cellule_t *copy;
int boolean = 0;
char *string2, *string3 = NULL;
cellule_t *c =NULL;
while(fgets(string1,100,fichier) != NULL)
{
string2 = strtok(string1,";");
string3 = strtok(NULL,";");
string3[strlen(string3)-1] = '[=11=]';
printf("string2 %s\n",string2);
printf("string3 %s\n",string3);
indice = hash_string(string2);
boolean = 0;
indice = recherche(tabMajeur,string2,&boolean,&c);
if(boolean != 1)
{
copy = tabMajeur[indice];
tabMajeur[indice] = creationCellule(string2,string3); (c: 64)
tabMajeur[indice]->suivant = copy;
}
}
}
cellule_t* creationCellule(char * mot, char *traduction)
{
cellule_t *nouveau = (cellule_t *) malloc(sizeof(cellule_t)); (c:24)
if(nouveau != NULL)
{
nouveau -> mot = strdup(mot);
nouveau -> traduction = strdup(traduction);
nouveau -> suivant = NULL;
}
return nouveau;
}
void libererMemorie(cellule_t **tabMajeur)
{
int i = 0;
cellule_t * cour;
cellule_t * copy;
for(i = 0 ; i < HASH_MAX; i++)
{
cour = tabMajeur[i];
while(cour != NULL)
{
copy = cour;
free(copy); (c:137)
cour = cour->suivant; (c:138)
}
}
}
valgrind 错误是:
enter image description here
valgrind 错误的文本是:
==2550== Memcheck, a memory error detector
==2550== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==2550== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==2550== Command: ./tp4
==2550==
string2 hello
string3 bonjour
string2 bye
string3 au revoir
string2 sorry
string3 pardon
string2 glass
string3 verre
La traduction est bonjour au revoir verre pardon
==2550== Invalid read of size 8
==2550== at 0x108E55: libererMemorie (tp4.c:138)
==2550== by 0x108F85: main (tp4.c:159)
==2550== Address 0x522ea40 is 16 bytes inside a block of size 24 free'd
==2550== at 0x4C30D3B: free (in
/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2550== by 0x108E50: libererMemorie (tp4.c:137)
==2550== by 0x108F85: main (tp4.c:159)
==2550== Block was alloc'd at
==2550== at 0x4C2FB0F: malloc (in
/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2550== by 0x108A5D: creationCellule (tp4.c:24)
==2550== by 0x108BD8: remplissage_hachage (tp4.c:64)
==2550== by 0x108F60: main (tp4.c:157)
==2550==
==2550==
==2550== HEAP SUMMARY:
==2550== in use at exit: 605 bytes in 9 blocks
==2550== total heap usage: 15 allocs, 6 frees, 5,821 bytes allocated
==2550==
==2550== LEAK SUMMARY:
==2550== definitely lost: 53 bytes in 8 blocks
==2550== indirectly lost: 0 bytes in 0 blocks
==2550== possibly lost: 0 bytes in 0 blocks
==2550== still reachable: 552 bytes in 1 blocks
==2550== suppressed: 0 bytes in 0 blocks
==2550== Rerun with --leak-check=full to see details of leaked memory
==2550==
==2550== For counts of detected and suppressed errors, rerun with: -v
==2550== ERROR SUMMARY: 4 errors from 1 contexts (suppressed: 0 from 0)
你能帮我找出问题所在吗?
"Invalid Read" 错误可能源于这样一个事实,即当您的散列 table 中的每个存储桶都有一个 singly-linked 列表时,您正试图释放列表节点,然后在释放当前节点后访问指向下一个节点的指针。
所以基本上在这里:
copy = cour;
free(copy);
cour = cour->suivant;
您正在创建未定义的行为,因为您正在释放节点,然后尝试通过 cour
指针访问释放的内存以获取链表中的下一个指针。将 copy
的值分配给 cour
只是复制了指针值本身。然后,您释放了 copy
和 cour
指向的内存,然后尝试访问已释放块中的内存。 Valgrind 肯定不会喜欢那样。
您只需将顺序更改为以下内容即可:
copy = cour;
cour = cour->suivant;
free(copy);
现在,在复制出指向下一个节点的指针后,释放当前节点中的内存,同时内存块仍然是有效的已分配内存块。
我正在使用哈希数组制作一个项目。我正在放一张我在网上找到的图片,向你们展示我正在尝试做什么。 image
所以我在main中像这样初始化了左边的大数组:
cellule_t * array[HASH_MAX] = {NULL};
然后我完成了所有插入以创建链表。我现在想做的是释放()所有分配给创建这一切的内存。所以,就像我没有为大数组使用 malloc 一样,我只需要释放链表并且我正在使用这个函数:
但是我从 Valgrind 得到了一些错误并且块没有被释放。 我将我使用的所有功能(包括主要功能)放在一起,以使其更加清晰。
typedef struct cell{
char *mot;
char *traduction;
struct cell *suivant;
}cellule_t;
int main()
{
int indice;
cellule_t *cel;
FILE*file = NULL;
char buffer[100] = "hello bye glass sorry";
cellule_t *tabMajeur[HASH_MAX] = {0};
file = fopen("fichier.txt","r");
remplissage_hachage(tabMajeur,file); (c:157)
affichageTraduction(tabMajeur,buffer);
libererMemorie(tabMajeur); (c:159)
}
void remplissage_hachage (cellule_t **tabMajeur,FILE *fichier)
{
char string1[20];
unsigned int indice = 0;
cellule_t *copy;
int boolean = 0;
char *string2, *string3 = NULL;
cellule_t *c =NULL;
while(fgets(string1,100,fichier) != NULL)
{
string2 = strtok(string1,";");
string3 = strtok(NULL,";");
string3[strlen(string3)-1] = '[=11=]';
printf("string2 %s\n",string2);
printf("string3 %s\n",string3);
indice = hash_string(string2);
boolean = 0;
indice = recherche(tabMajeur,string2,&boolean,&c);
if(boolean != 1)
{
copy = tabMajeur[indice];
tabMajeur[indice] = creationCellule(string2,string3); (c: 64)
tabMajeur[indice]->suivant = copy;
}
}
}
cellule_t* creationCellule(char * mot, char *traduction)
{
cellule_t *nouveau = (cellule_t *) malloc(sizeof(cellule_t)); (c:24)
if(nouveau != NULL)
{
nouveau -> mot = strdup(mot);
nouveau -> traduction = strdup(traduction);
nouveau -> suivant = NULL;
}
return nouveau;
}
void libererMemorie(cellule_t **tabMajeur)
{
int i = 0;
cellule_t * cour;
cellule_t * copy;
for(i = 0 ; i < HASH_MAX; i++)
{
cour = tabMajeur[i];
while(cour != NULL)
{
copy = cour;
free(copy); (c:137)
cour = cour->suivant; (c:138)
}
}
}
valgrind 错误是: enter image description here
valgrind 错误的文本是:
==2550== Memcheck, a memory error detector
==2550== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==2550== Using Valgrind-3.13.0 and LibVEX; rerun with -h for copyright info
==2550== Command: ./tp4
==2550==
string2 hello
string3 bonjour
string2 bye
string3 au revoir
string2 sorry
string3 pardon
string2 glass
string3 verre
La traduction est bonjour au revoir verre pardon
==2550== Invalid read of size 8
==2550== at 0x108E55: libererMemorie (tp4.c:138)
==2550== by 0x108F85: main (tp4.c:159)
==2550== Address 0x522ea40 is 16 bytes inside a block of size 24 free'd
==2550== at 0x4C30D3B: free (in
/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2550== by 0x108E50: libererMemorie (tp4.c:137)
==2550== by 0x108F85: main (tp4.c:159)
==2550== Block was alloc'd at
==2550== at 0x4C2FB0F: malloc (in
/usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==2550== by 0x108A5D: creationCellule (tp4.c:24)
==2550== by 0x108BD8: remplissage_hachage (tp4.c:64)
==2550== by 0x108F60: main (tp4.c:157)
==2550==
==2550==
==2550== HEAP SUMMARY:
==2550== in use at exit: 605 bytes in 9 blocks
==2550== total heap usage: 15 allocs, 6 frees, 5,821 bytes allocated
==2550==
==2550== LEAK SUMMARY:
==2550== definitely lost: 53 bytes in 8 blocks
==2550== indirectly lost: 0 bytes in 0 blocks
==2550== possibly lost: 0 bytes in 0 blocks
==2550== still reachable: 552 bytes in 1 blocks
==2550== suppressed: 0 bytes in 0 blocks
==2550== Rerun with --leak-check=full to see details of leaked memory
==2550==
==2550== For counts of detected and suppressed errors, rerun with: -v
==2550== ERROR SUMMARY: 4 errors from 1 contexts (suppressed: 0 from 0)
你能帮我找出问题所在吗?
"Invalid Read" 错误可能源于这样一个事实,即当您的散列 table 中的每个存储桶都有一个 singly-linked 列表时,您正试图释放列表节点,然后在释放当前节点后访问指向下一个节点的指针。
所以基本上在这里:
copy = cour;
free(copy);
cour = cour->suivant;
您正在创建未定义的行为,因为您正在释放节点,然后尝试通过 cour
指针访问释放的内存以获取链表中的下一个指针。将 copy
的值分配给 cour
只是复制了指针值本身。然后,您释放了 copy
和 cour
指向的内存,然后尝试访问已释放块中的内存。 Valgrind 肯定不会喜欢那样。
您只需将顺序更改为以下内容即可:
copy = cour;
cour = cour->suivant;
free(copy);
现在,在复制出指向下一个节点的指针后,释放当前节点中的内存,同时内存块仍然是有效的已分配内存块。