C 瓦尔格兰德坚持认为';堆上仍然有内存,但我';我正在释放指向堆的唯一指针

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

我正在使用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 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 not
exit
的功劳。出现错误时返回给调用者。让调用者决定该做什么。鉴于您发布的代码,我无法使用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 not
exit
的功劳。出现错误时返回给调用者。让调用者决定该做什么。鉴于您发布的代码,我无法使用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