[英]Valgrind detects memory leak despite the fact memory has been freed
我有一个文件“ a”,包含2000个字符,仅char“ a”,没有空格。
然后,我得到了这段代码,该代码在循环中运行,将其添加到缓冲区中,如果达到限制,最终将重新分配,并在出现错误时释放strBuffer变量。
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
int maxS = 200;
int numericExpression;
int strLength;
char *strBuffer;
strBuffer = malloc(sizeof(char)*maxS+1);
if(strBuffer == NULL)
{
printf("Failed to allocate requested memory!\n");
free(strBuffer);
strLength = sizeof(strBuffer);
printf("Freed %d bytes of memory!\n", strLength);
exit(99);
}
else
{
numericExpression = sizeof(char)*maxS+1;
printf("Alocated: %d Bytes of memory.\n", numericExpression);
}
// while simulation
int fcv = -1;
int numEx;
// file opening simulation
FILE* fd = fopen("a", "r");
int c;
while((c=fgetc(fd) != EOF)) // condition to make sure we realloc only once
{
fcv++;
strBuffer[fcv] = c;
if(fcv == (maxS))
{
printf("Additional memory space required!\n");
int strlensize = strlen(strBuffer);
numEx = (sizeof(char)*(2*strlensize));
strBuffer = realloc(strBuffer, numEx);
if(strBuffer == NULL)
{
printf("Failed to allocate requested memory!\n");
strLength = sizeof(strBuffer);
free(strBuffer);
printf("Freed %d bytes of memory!\n", strLength);
exit(99);
}
else
{
maxS = numEx;
printf("Reallocation successful!\n");
printf("Alocated: %d Bytes of memory.\n", numEx);
}
}
}
strLength = sizeof(strBuffer);
free(strBuffer);
printf("Freed %d bytes of memory!\n", strLength);
}
问题是它最终告诉我,我只释放了8个字节的内存。 我想这是因为sizeof(strBuffer)没有响应预期的大小。 当我改用strlen(strBuffer)时,我仅释放2001个字节。
我想这可能只是打印出释放的字节数的问题。 我可能做错了。 因此,也许我只是无法说出我释放了多少字节。 但是然后我尝试使用valgrind,它告诉我,我的内存不足,导致内存泄漏。 但是在程序的每个分支中,我都可以释放strBuffer使用的内存。
当我通过valgrind(“ valgrind ./realloc”)运行它时,它告诉我:
==780== Memcheck, a memory error detector
==780== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==780== Using Valgrind-3.10.0.SVN and LibVEX; rerun with -h for copyright info
==780== Command: ./realloc
==780==
Alocated: 201 Bytes of memory.
Additional memory space required!
==780== Invalid read of size 1
==780== at 0x4C2E0F4: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==780== by 0x400846: main (in /home/dan/Desktop/test_ifj/realloc)
==780== Address 0x51fd109 is 0 bytes after a block of size 201 alloc'd
==780== at 0x4C2AB80: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==780== by 0x40078C: main (in /home/dan/Desktop/test_ifj/realloc)
==780==
Reallocation successful!
Alocated: 402 Bytes of memory.
==780== Invalid write of size 1
==780== at 0x400823: main (in /home/dan/Desktop/test_ifj/realloc)
==780== Address 0x51fd562 is 0 bytes after a block of size 402 alloc'd
==780== at 0x4C2CE8E: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==780== by 0x400866: main (in /home/dan/Desktop/test_ifj/realloc)
==780==
Additional memory space required!
Reallocation successful!
Alocated: 806 Bytes of memory.
Additional memory space required!
==780== Conditional jump or move depends on uninitialised value(s)
==780== at 0x4C2E0F8: strlen (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==780== by 0x400846: main (in /home/dan/Desktop/test_ifj/realloc)
==780==
Reallocation successful!
Alocated: 804 Bytes of memory.
Freed 8 bytes of memory!
==780==
==780== HEAP SUMMARY:
==780== in use at exit: 568 bytes in 1 blocks
==780== total heap usage: 5 allocs, 4 frees, 2,781 bytes allocated
==780==
==780== LEAK SUMMARY:
==780== definitely lost: 0 bytes in 0 blocks
==780== indirectly lost: 0 bytes in 0 blocks
==780== possibly lost: 0 bytes in 0 blocks
==780== still reachable: 568 bytes in 1 blocks
==780== suppressed: 0 bytes in 0 blocks
==780== Rerun with --leak-check=full to see details of leaked memory
==780==
==780== For counts of detected and suppressed errors, rerun with: -v
==780== Use --track-origins=yes to see where uninitialised values come from
==780== ERROR SUMMARY: 1200 errors from 3 contexts (suppressed: 0 from 0)
如何正确释放已分配的内存? 这样不会引起内存泄漏吗? 最终-我做错了吗,还有更好的方法吗? 谢谢您的帮助。
我遵循了建议,并在1个上下文中将其纠正为3个错误。 这是我的代码现在的样子:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
int maxS = 200;
int numericExpression;
char *strBuffer;
strBuffer = malloc((maxS+1));
if(strBuffer == NULL)
{
printf("Failed to allocate requested memory!\n");
printf("Freed %d bytes of memory!\n", maxS);
exit(99);
}
else
{
numericExpression = sizeof(char)*maxS+1;
printf("Alocated: %d Bytes of memory.\n", numericExpression);
}
// while simulation
int fcv = -1;
int numEx;
// file opening simulation
FILE* fd = fopen("a", "r");
if(fd == NULL)
{
printf("Error opening a file!\n");
if(strBuffer != NULL)
{free(strBuffer);}
exit(99);
}
int c;
char *tmpBuffer;
while((c=fgetc(fd)) != EOF) // condition to make sure we realloc only once
{
fcv++;
strBuffer[fcv] = c;
if(fcv == (maxS))
{
printf("Additional memory space required!\n");
numEx = ((2*fcv));
tmpBuffer = realloc(strBuffer, numEx);
if(!tmpBuffer)
{
free(strBuffer);
printf("Realloc() failed!\n");
exit(99);
}
else
{
strBuffer = tmpBuffer;
}
if(strBuffer == NULL)
{
printf("Failed to allocate requested memory!\n");
printf("Freed %d bytes of memory!\n", maxS); // well this is questionable, I think
exit(99);
}
else
{
maxS = numEx;
printf("Reallocation successful!\n");
printf("Alocated: %d Bytes of memory.\n", maxS);
}
}
}
free(strBuffer);fclose(fd); // ADDED, still errors occur
printf("Freed %d bytes of memory!\n", maxS);
}
使用相同的valgrind调用(“ valgrind ./realloc”),我得到了:
==1213== Invalid write of size 1
==1213== at 0x4007FD: main (in /home/dan/Desktop/test_ifj/realloc)
==1213== Address 0x51fd560 is 0 bytes after a block of size 400 alloc'd
==1213== at 0x4C2CE8E: realloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==1213== by 0x400831: main (in /home/dan/Desktop/test_ifj/realloc)
==1213==
Additional memory space required!
Reallocation successful!
Alocated: 800 Bytes of memory.
Additional memory space required!
Reallocation successful!
Alocated: 1600 Bytes of memory.
Additional memory space required!
Reallocation successful!
Alocated: 3200 Bytes of memory.
Freed 3200 bytes of memory!
==1213==
==1213== HEAP SUMMARY:
==1213== in use at exit: 568 bytes in 1 blocks
==1213== total heap usage: 6 allocs, 5 frees, 6,769 bytes allocated
==1213==
==1213== LEAK SUMMARY:
==1213== definitely lost: 0 bytes in 0 blocks
==1213== indirectly lost: 0 bytes in 0 blocks
==1213== possibly lost: 0 bytes in 0 blocks
==1213== still reachable: 568 bytes in 1 blocks
==1213== suppressed: 0 bytes in 0 blocks
==1213== Rerun with --leak-check=full to see details of leaked memory
==1213==
==1213== For counts of detected and suppressed errors, rerun with: -v
==1213== ERROR SUMMARY: 3 errors from 1 contexts (suppressed: 0 from 0)
任何提示可能导致这一问题?
这是你的问题:
strBuffer = realloc(strBuffer, numEx);
如果您对realloc()
调用失败,则它将返回一个空指针,但不会释放原始的内存分配。
您需要先检查返回值,如果成功,则将其分配给原始指针:
char *tmpBuffer = realloc(strBuffer, numEx);
if (!tmpBuffer) {
free(strBuffer);
puts("realloc() failed");
exit(1);
}
else {
strBuffer = tmpBuffer;
}
您的代码还有其他一些问题,包括:
如果strBuffer为NULL,则没有意义将其传递给free()。
sizeof()
不是运行时函数,因此它不知道分配了多少内存。
strBuffer = malloc(sizeof(char)*maxS+1);
有点草率。 我认为您的意思是strBuffer = malloc(sizeof(char)*(maxS+1));
,但您只需将strBuffer = malloc(maxS+1);
因为sizeof(char)
根据定义为1。
好吧,到目前为止,每个人都为您提供了非常重要的建议,您应该考虑使用它们(主要是tempBuffer
)。 但是您的问题是您忘记关闭文件描述符:
fclose(fd);
同样, sizeof
是编译时间,因此它不能给您动态分配的内存大小,并且strlen
需要一个\\n
字符才能工作。 计算分配和释放的内存是一项艰巨的任务,它的解决方案并不是那么简单。
我执行了更新的代码, 从1个上下文中仅收到1个错误 ,可以通过更改以下行来解决: tmpBuffer = realloc(strBuffer, numEx + 1);
除此之外, fclose(fd)之后的所有内存都是可用的。 我在使用gcc 4.8.1的Ubuntu 12.04计算机上。
while((c=fgetc(fd) != EOF))
应该是while((c=fgetc(fd)) != EOF)
。 这样做的结果是您试图在字符串中存储1
而不是读取的字符。
内存问题源于strlen(strBuffer);
。 您在非空终止的字符串上调用strlen
,这会导致未定义的行为。 (这在valgrind报告中显示为“ strlen
中大小为1的无效读取)。
要解决此问题,请摆脱strlenSize
并执行以下操作:
maxS = 2 * maxS;
strBuffer = realloc(strBuffer, maxS + 1);
请注意,如果要在内存不足的情况下使用“干净”的valgrind,则需要在将其分配给strBuffer
之前检查realloc
的返回值,如提示ossifrage所指出。
注意 您的错误处理代码不正确。 sizeof(strBuffer)
查找指针的大小。 您要打印的值为maxS
。 另外, free(NULL)
无效; 在调用exit()
块之后没有else
块是没有意义的。
this compiles, and does the job
it includes error handling
it eliminated many meaningless variables
it eliminates the errors in the logic of the OPs code
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int main()
{
int maxS = 200; // current allocation size
char *strBuffer = NULL;
if( NULL == (strBuffer = malloc(maxS) ) )
{ // then, malloc failed
perror( "malloc failed" );
exit(99);
}
// implied else, malloc successful
printf("Alocated: %d Bytes of memory.\n", )maxS+1));
// file opening simulation
FILE* fd = fopen("a", "r");
if(fd == NULL)
{ // then fopen failed
perror( "fopen failed for file: a" );
free(strBuffer);
exit(99);
}
// implied else, fopen successful
int c; // receives input char from fgetc()
int fcv = 0; // index into malloc'd memory
// tmpBuffer used in realloc()
// so will not lose pointer to already allocated memory
// in case realloc() fails
char *tmpBuffer;
while((c=fgetc(fd)) != EOF)
{
strBuffer[fcv] = c;
fcv++;
if(fcv >= maxS)
{
printf("Additional memory space required!\n");
if( NULL == ()tmpBuffer = realloc(strBuffer, 2*maxS) )
{
perror( "realloc failed" );
free(strBuffer);
fclose(fd);
exit(99);
}
// implied else, realloc successful
maxS *= 2; // only update after being sure realloc successful
strBuffer = tmpBuffer;
printf("Reallocation successful!\n");
printf("Allocated: %d Bytes of memory.\n", maxS);
} // end if
} // end while
free(strBuffer);
fclose(fd);
printf("Freed %d bytes of memory!\n", maxS);
return( 0 );
} // end function: main
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.