如何释放分配的内存而不丢失其价值
How to free an allocated memory without losing its value
你好,我用 C 编写了这个函数,它接受一串单词和 returns 一个二维字符数组,每个 case 都以正确的顺序初始化为一个单词,我编译并完成了分配的任务
char **decompose_string(char *string)
{
int i,j=0;
char* temp=malloc(sizeof(char*));
char **words_array=malloc((string_words_number(string)+1)*sizeof(char*)); //string_words_number return the number of words in string string
for(i=0;i<string_words_number(string);i++)
{
temp=NULL;
int l=0;
while(string[j]!=' ' && *string)
{
temp=realloc(temp,(l+1)*sizeof(char));
temp[l]=string[j];
j++;l++;
}
j++;
temp[l]='[=10=]';
tab_mots=realloc(words_array,(string_words_number(string)+1)*sizeof(char)*(j-1));
words_array[i]=temp;
}
words_array[i]=NULL;
return words_array;}
还有我的主要:
int main()
{
char* string1= "word1 and word2 and word3";
printf("Our initial string: %s\n",string1);
char** words_array1;
printf("After decomposition:\n");
words_array1=decompose_string(string1);
display_words_array(words_array1); //displays each element of the array in a line
words_array1=destroy_array(words_array1);
return 0;}
但是当我执行 valgrind 命令以查看是否存在任何内存泄漏时,结果是这样的:
==4648== Memcheck, a memory error detector
==4648== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==4648== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==4648== Command: ./test_csvl
==4648==
Our initial array: word1 and word2 and word3
After decomposition:
==4648== Invalid write of size 1
==4648== at 0x4009D9: decompose_string (in /home/omaima/2I001/TME3/test_csvl)
==4648== by 0x40078F: main (in /home/omaima/2I001/TME3/test_csvl)
==4648== Address 0x5204634 is 0 bytes after a block of size 4 alloc'd
==4648== at 0x4C2FD5F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4648== by 0x40097D: decompose_string (in /home/omaima/2I001/TME3/test_csvl)
==4648== by 0x40078F: main (in /home/omaima/2I001/TME3/test_csvl)
==4648==
==4648== Invalid read of size 1
==4648== at 0x4C30F74: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4648== by 0x4EA969B: puts (ioputs.c:35)
==4648== by 0x400888: display_words_array (in /home/omaima/2I001/TME3/test_csvl)
==4648== by 0x40079F: main (in /home/omaima/2I001/TME3/test_csvl)
==4648== Address 0x5204634 is 0 bytes after a block of size 4 alloc'd
==4648== at 0x4C2FD5F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4648== by 0x40097D: decompose_string (in /home/omaima/2I001/TME3/test_csvl)
==4648== by 0x40078F: main (in /home/omaima/2I001/TME3/test_csvl)
==4648==
word1
and
word2
and
word3
==4648==
==4648== HEAP SUMMARY:
==4648== in use at exit: 8 bytes in 1 blocks
==4648== total heap usage: 30 allocs, 29 frees, 1,545 bytes allocated
==4648==
==4648== LEAK SUMMARY:
==4648== definitely lost: 8 bytes in 1 blocks
==4648== indirectly lost: 0 bytes in 0 blocks
==4648== possibly lost: 0 bytes in 0 blocks
==4648== still reachable: 0 bytes in 0 blocks
==4648== suppressed: 0 bytes in 0 blocks
==4648== Rerun with --leak-check=full to see details of leaked memory
==4648==
==4648== For counts of detected and suppressed errors, rerun with: -v
==4648== ERROR SUMMARY: 9 errors from 2 contexts (suppressed: 0 from 0)
我知道缺少的 free 是函数中用于 temp 的 free,但如果我释放它,我最终将失去我的数组所需的值。所以我的问题是我可以在不失去它的价值的情况下释放它吗?或任何其他解决方案,以保证我的功能的功能和消除任何内存泄漏。谢谢你的时间。
抱歉,我忘了这是我用来释放分配的函数 space:
char **destroy_words_array( char** words_array)
{
int i;
for(i=0;i<count_words(words_array);i++) free(words_array[i]); //wount_words return the number of elements of the array
free(words_array);
return words_array;
}
在 for 循环之前你有
char* temp=malloc(sizeof(char*));
但是 for 循环中的第一件事是
temp=NULL;
所以temp
指向的内存丢失了。如果您 运行 在 64 位计算机上执行此程序,您将看到大小为 8 的内存泄漏。删除 temp
的第一个声明并将 for 循环中的第一行更改为
char* temp = NULL;
另一个问题是内部 while 循环的条件:
while(chaine[j]!=' ' && *chaine)
因为你不推进chaine
指针,所以*chaine
的值不会改变。您可能打算在这里写 chaine[j]
:
while(chaine[j]!=' ' && chaine[j])
相当于
while(chaine[j]!=' ' && chaine[j]!='[=15=]')
内存泄漏不是您认为的那样。它发生在你的函数开始时:
char* temp=malloc(sizeof(char*));
char **words_array=malloc((string_words_number(string)+1)*sizeof(char*));
for(i=0;i<string_words_number(string);i++)
{
temp=NULL;
您为指向 temp
的指针分配了 space,但是当您进入 for
循环时您覆盖了该指针。删除那个 malloc
调用,泄漏就消失了。
但是你有一个更大的问题,那就是读取和写入超过分配缓冲区的末尾。这发生在这里:
temp=NULL;
int l=0;
while(string[j]!=' ' && *string)
{
temp=realloc(temp,(l+1)*sizeof(char));
temp[l]=string[j];
j++;l++;
}
j++;
temp[l]='[=11=]';
假设有问题的字符串有两个字符需要读取。在循环的第一次迭代中,l
为 0,因此您将 l+1 == 1
字节分配给 temp
。然后你写入 temp[l] == temp[0]
,这很好,然后你将 l
递增到 1。在下一次迭代中,你为 temp
分配 l+1 == 2
字节,写入 temp[l] == temp[1]
,并将 l
增加到 2。到目前为止仍然很好。
问题是当您在循环外执行 temp[l]='[=26=]';
时。 l
现在是 2,分配的内存大小是 2,所以你要在数组末尾后写入一个元素。
这里需要多分配一个字节:
j++;
temp=realloc(temp,(l+1)*sizeof(char));
temp[l]='[=12=]';
另请注意,您应该在整个代码中检查 malloc
和 realloc
的 return 值,以防失败。
此外,您没有正确检查 string
的结尾。你需要做的:
while(string[j]!=' ' && string[j]!=0)
你好,我用 C 编写了这个函数,它接受一串单词和 returns 一个二维字符数组,每个 case 都以正确的顺序初始化为一个单词,我编译并完成了分配的任务
char **decompose_string(char *string)
{
int i,j=0;
char* temp=malloc(sizeof(char*));
char **words_array=malloc((string_words_number(string)+1)*sizeof(char*)); //string_words_number return the number of words in string string
for(i=0;i<string_words_number(string);i++)
{
temp=NULL;
int l=0;
while(string[j]!=' ' && *string)
{
temp=realloc(temp,(l+1)*sizeof(char));
temp[l]=string[j];
j++;l++;
}
j++;
temp[l]='[=10=]';
tab_mots=realloc(words_array,(string_words_number(string)+1)*sizeof(char)*(j-1));
words_array[i]=temp;
}
words_array[i]=NULL;
return words_array;}
还有我的主要:
int main()
{
char* string1= "word1 and word2 and word3";
printf("Our initial string: %s\n",string1);
char** words_array1;
printf("After decomposition:\n");
words_array1=decompose_string(string1);
display_words_array(words_array1); //displays each element of the array in a line
words_array1=destroy_array(words_array1);
return 0;}
但是当我执行 valgrind 命令以查看是否存在任何内存泄漏时,结果是这样的:
==4648== Memcheck, a memory error detector
==4648== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==4648== Using Valgrind-3.11.0 and LibVEX; rerun with -h for copyright info
==4648== Command: ./test_csvl
==4648==
Our initial array: word1 and word2 and word3
After decomposition:
==4648== Invalid write of size 1
==4648== at 0x4009D9: decompose_string (in /home/omaima/2I001/TME3/test_csvl)
==4648== by 0x40078F: main (in /home/omaima/2I001/TME3/test_csvl)
==4648== Address 0x5204634 is 0 bytes after a block of size 4 alloc'd
==4648== at 0x4C2FD5F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4648== by 0x40097D: decompose_string (in /home/omaima/2I001/TME3/test_csvl)
==4648== by 0x40078F: main (in /home/omaima/2I001/TME3/test_csvl)
==4648==
==4648== Invalid read of size 1
==4648== at 0x4C30F74: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4648== by 0x4EA969B: puts (ioputs.c:35)
==4648== by 0x400888: display_words_array (in /home/omaima/2I001/TME3/test_csvl)
==4648== by 0x40079F: main (in /home/omaima/2I001/TME3/test_csvl)
==4648== Address 0x5204634 is 0 bytes after a block of size 4 alloc'd
==4648== at 0x4C2FD5F: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==4648== by 0x40097D: decompose_string (in /home/omaima/2I001/TME3/test_csvl)
==4648== by 0x40078F: main (in /home/omaima/2I001/TME3/test_csvl)
==4648==
word1
and
word2
and
word3
==4648==
==4648== HEAP SUMMARY:
==4648== in use at exit: 8 bytes in 1 blocks
==4648== total heap usage: 30 allocs, 29 frees, 1,545 bytes allocated
==4648==
==4648== LEAK SUMMARY:
==4648== definitely lost: 8 bytes in 1 blocks
==4648== indirectly lost: 0 bytes in 0 blocks
==4648== possibly lost: 0 bytes in 0 blocks
==4648== still reachable: 0 bytes in 0 blocks
==4648== suppressed: 0 bytes in 0 blocks
==4648== Rerun with --leak-check=full to see details of leaked memory
==4648==
==4648== For counts of detected and suppressed errors, rerun with: -v
==4648== ERROR SUMMARY: 9 errors from 2 contexts (suppressed: 0 from 0)
我知道缺少的 free 是函数中用于 temp 的 free,但如果我释放它,我最终将失去我的数组所需的值。所以我的问题是我可以在不失去它的价值的情况下释放它吗?或任何其他解决方案,以保证我的功能的功能和消除任何内存泄漏。谢谢你的时间。
抱歉,我忘了这是我用来释放分配的函数 space:
char **destroy_words_array( char** words_array)
{
int i;
for(i=0;i<count_words(words_array);i++) free(words_array[i]); //wount_words return the number of elements of the array
free(words_array);
return words_array;
}
在 for 循环之前你有
char* temp=malloc(sizeof(char*));
但是 for 循环中的第一件事是
temp=NULL;
所以temp
指向的内存丢失了。如果您 运行 在 64 位计算机上执行此程序,您将看到大小为 8 的内存泄漏。删除 temp
的第一个声明并将 for 循环中的第一行更改为
char* temp = NULL;
另一个问题是内部 while 循环的条件:
while(chaine[j]!=' ' && *chaine)
因为你不推进chaine
指针,所以*chaine
的值不会改变。您可能打算在这里写 chaine[j]
:
while(chaine[j]!=' ' && chaine[j])
相当于
while(chaine[j]!=' ' && chaine[j]!='[=15=]')
内存泄漏不是您认为的那样。它发生在你的函数开始时:
char* temp=malloc(sizeof(char*));
char **words_array=malloc((string_words_number(string)+1)*sizeof(char*));
for(i=0;i<string_words_number(string);i++)
{
temp=NULL;
您为指向 temp
的指针分配了 space,但是当您进入 for
循环时您覆盖了该指针。删除那个 malloc
调用,泄漏就消失了。
但是你有一个更大的问题,那就是读取和写入超过分配缓冲区的末尾。这发生在这里:
temp=NULL;
int l=0;
while(string[j]!=' ' && *string)
{
temp=realloc(temp,(l+1)*sizeof(char));
temp[l]=string[j];
j++;l++;
}
j++;
temp[l]='[=11=]';
假设有问题的字符串有两个字符需要读取。在循环的第一次迭代中,l
为 0,因此您将 l+1 == 1
字节分配给 temp
。然后你写入 temp[l] == temp[0]
,这很好,然后你将 l
递增到 1。在下一次迭代中,你为 temp
分配 l+1 == 2
字节,写入 temp[l] == temp[1]
,并将 l
增加到 2。到目前为止仍然很好。
问题是当您在循环外执行 temp[l]='[=26=]';
时。 l
现在是 2,分配的内存大小是 2,所以你要在数组末尾后写入一个元素。
这里需要多分配一个字节:
j++;
temp=realloc(temp,(l+1)*sizeof(char));
temp[l]='[=12=]';
另请注意,您应该在整个代码中检查 malloc
和 realloc
的 return 值,以防失败。
此外,您没有正确检查 string
的结尾。你需要做的:
while(string[j]!=' ' && string[j]!=0)