C 瓦尔格兰德坚持认为';堆上仍然有内存,但我';我正在释放指向堆的唯一指针
我正在使用Valgrind查找代码中的内存泄漏,根据输出,仍然可以访问17个字节,1个alloc,0个frees:C 瓦尔格兰德坚持认为';堆上仍然有内存,但我';我正在释放指向堆的唯一指针,c,valgrind,free,calloc,C,Valgrind,Free,Calloc,我正在使用Valgrind查找代码中的内存泄漏,根据输出,仍然可以访问17个字节,1个alloc,0个frees: ==9413== ==9413== HEAP SUMMARY: ==9413== in use at exit: 17 bytes in 1 blocks ==9413== total heap usage: 1 allocs, 0 frees, 17 bytes allocated ==9413== ==9413== 17 bytes in 1 blocks ar
==9413==
==9413== HEAP SUMMARY:
==9413== in use at exit: 17 bytes in 1 blocks
==9413== total heap usage: 1 allocs, 0 frees, 17 bytes allocated
==9413==
==9413== 17 bytes in 1 blocks are still reachable in loss record 1 of 1
==9413== at 0x402C109: calloc (in /usr/lib/valgrind/vgpreload_memcheck-x86-linux.so)
==9413== by 0x80485F6: main (question3.c:21)
==9413==
==9413== LEAK SUMMARY:
==9413== definitely lost: 0 bytes in 0 blocks
==9413== indirectly lost: 0 bytes in 0 blocks
==9413== possibly lost: 0 bytes in 0 blocks
==9413== still reachable: 17 bytes in 1 blocks
==9413== suppressed: 0 bytes in 0 blocks
==9413==
==9413== For counts of detected and suppressed errors, rerun with: -v
==9413== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
问题是,我的代码中只有一个calloc,我正在释放指针:
void checkInput(int err) {
if (!err || err == EOF) {
printf("\nInvalid input!\n");
exit(1);
}
}
#define N 17
int main() {
char bufferStack[N] = { 'a' };
char * bufferHeap = calloc(N, sizeof(char));
char junk[N];
printf("Enter a string no more than 16 chars long\n0123456789012345\n");
checkInput(scanf("%16[^\n]", bufferStack));
printf("BufferStack: %s\n", bufferStack);
checkInput(scanf("%16[\n]", junk));
checkInput(scanf("%16[^\n]", bufferHeap));
printf("BufferHeap: %s\n", bufferHeap);
free(bufferHeap);
return 0;
}
我不确定内存在哪里(或者更确切地说是如何)泄漏。如果有人能帮我找到错误或解决问题,我会非常感激。谢谢。如果您在第一次提示中输入的字符超过16个,则对
scanf
的第一次调用将拾取前16个字符,将剩余的字符保留在输入缓冲区中
然后,当第二个scanf
执行时,它需要换行符。下一个字符不是换行符,而是第一个提示留下的字符。这导致不匹配,因此scanf
返回0。这会导致checkInput
打印错误消息并调用exit
,它会立即退出程序,而不会释放内存。这就是“仍然可访问”内存的来源
您需要重新构造代码,以便所有代码路径
都能释放分配的内存。如果在第一次提示中输入的字符超过16个,则对scanf
的第一次调用将拾取前16个字符,将剩余的字符保留在输入缓冲区中
然后,当第二个scanf
执行时,它需要换行符。下一个字符不是换行符,而是第一个提示留下的字符。这导致不匹配,因此scanf
返回0。这会导致checkInput
打印错误消息并调用exit
,它会立即退出程序,而不会释放内存。这就是“仍然可访问”内存的来源
您需要重新构造代码,以便所有代码路径都可以释放分配的内存。如果checkInput函数失败,程序可能会在不释放内存的情况下退出。在函数中使用valgrindDo notexit
的功劳。出现错误时返回给调用者。让调用者决定该做什么。鉴于您发布的代码,我无法使用linux 3.19.8-100和valgrind 3.9.0再现您的输出。我的退出(在我输入两行文本后)说“在退出时使用:0块中的0字节”。我建议您将代码放在循环中迭代,直到stdin结束从几百行的输入文件重定向stdin。在Valgrind下运行此代码时,输入是什么?在Valgrind下运行此代码时,是否看到打印的“BufferHeap:%s”
消息?OT:调用任何堆分配函数时:calloc()malloc()
和realloc()
始终检查(!=NULL)以确保操作成功。如果不成功,调用perror(“calloc失败”)
因此,您的错误消息和系统认为发生错误的文本原因都被输出到stderr
。如果您的checkInput功能失败,程序可能会在不执行空闲操作的情况下退出。在函数中使用valgrindDo notexit
的功劳。出现错误时返回给调用者。让调用者决定该做什么。鉴于您发布的代码,我无法使用linux 3.19.8-100和valgrind 3.9.0再现您的输出。我的退出(在我输入两行文本后)说“在退出时使用:0块中的0字节”。我建议您将代码放在循环中迭代,直到stdin结束从几百行的输入文件重定向stdin。在Valgrind下运行此代码时,输入是什么?在Valgrind下运行此代码时,是否看到打印的“BufferHeap:%s”
消息?OT:调用任何堆分配函数时:calloc()malloc()
和realloc()
始终检查(!=NULL)以确保操作成功。如果不成功,调用perror(“calloc失败”)
因此,您的错误消息和系统认为发生错误的文本原因都会输出到stderr
。