为什么 Valgrind 在 calloc 语句上显示内存泄漏
Why does Valgrind show a memory leak on a calloc statement
我正在尝试学习一些东西(作为一种爱好)并尝试学习使用 Valgrind。然而,这对我来说似乎没有意义。似乎 Valgrind 说当我在使用任何东西之前用 calloc 分配字节时,字节丢失了!有人可以解释这里发生了什么以及为什么第二个程序有效吗?我在 Eclipse 中以调试模式编译程序,并在调试可执行文件上编译 运行 Valgrind。
程序如下:
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4
5 int main(void) {
6
7 char* origstr = calloc(37, sizeof(char*));
8 char* newsubstr = calloc(9, sizeof(char*));
9
10 origstr = "TheQuickBrownFoxJumpedOverTheLazyDog";
11
12 strncpy(newsubstr, origstr + 8, 8);
13 printf("SubString is: %s\n", newsubstr);
14
15 free(newsubstr);
16 free(origstr);
17 return 0;
18 }
这是 Valgrind 给我的:
$ valgrind --tool=memcheck --leak-check=full ./test
==25404== Memcheck, a memory error detector
==25404== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==25404== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==25404== Command: ./test
==25404==
SubString is: BrownFox
==25404== Invalid free() / delete / delete[] / realloc()
==25404== at 0x4C29E90: free (vg_replace_malloc.c:473)
==25404== by 0x400665: main (test.c:16)
==25404== Address 0x4006f8 is not stack'd, malloc'd or (recently) free'd
==25404==
==25404==
==25404== HEAP SUMMARY:
==25404== in use at exit: 296 bytes in 1 blocks
==25404== total heap usage: 2 allocs, 2 frees, 368 bytes allocated
==25404==
==25404== 296 bytes in 1 blocks are definitely lost in loss record 1 of 1
==25404== at 0x4C2AD10: calloc (vg_replace_malloc.c:623)
==25404== by 0x4005FC: main (test.c:7)
==25404==
==25404== LEAK SUMMARY:
==25404== definitely lost: 296 bytes in 1 blocks
==25404== indirectly lost: 0 bytes in 0 blocks
==25404== possibly lost: 0 bytes in 0 blocks
==25404== still reachable: 0 bytes in 0 blocks
==25404== suppressed: 0 bytes in 0 blocks
==25404==
==25404== For counts of detected and suppressed errors, rerun with: -v
==25404== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
如果我删除两个 free() 语句,这就是 Valgrind 给我的:
$ valgrind --tool=memcheck --leak-check=full ./test
==25597== Memcheck, a memory error detector
==25597== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==25597== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==25597== Command: ./test
==25597==
SubString is: BrownFox
==25597==
==25597== HEAP SUMMARY:
==25597== in use at exit: 368 bytes in 2 blocks
==25597== total heap usage: 2 allocs, 0 frees, 368 bytes allocated
==25597==
==25597== 72 bytes in 1 blocks are definitely lost in loss record 1 of 2
==25597== at 0x4C2AD10: calloc (vg_replace_malloc.c:623)
==25597== by 0x4005BF: main (test.c:8)
==25597==
==25597== 296 bytes in 1 blocks are definitely lost in loss record 2 of 2
==25597== at 0x4C2AD10: calloc (vg_replace_malloc.c:623)
==25597== by 0x4005AC: main (test.c:7)
==25597==
==25597== LEAK SUMMARY:
==25597== definitely lost: 368 bytes in 2 blocks
==25597== indirectly lost: 0 bytes in 0 blocks
==25597== possibly lost: 0 bytes in 0 blocks
==25597== still reachable: 0 bytes in 0 blocks
==25597== suppressed: 0 bytes in 0 blocks
==25597==
==25597== For counts of detected and suppressed errors, rerun with: -v
==25597== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
现在,如果我 运行 这个程序:
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4
5 int main(void) {
6
7 char* origstr;
8 char* newsubstr = calloc(9, sizeof(char*));
9
10 origstr = "TheQuickBrownFoxJumpedOverTheLazyDog";
11
12 strncpy(newsubstr, origstr + 8, 8);
13 printf("SubString is: %s\n", newsubstr);
14
15 free(newsubstr);
16
17 return 0;
18 }
说明一切正常:
$ valgrind --tool=memcheck --leak-check=full ./test
==25862== Memcheck, a memory error detector
==25862== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==25862== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==25862== Command: ./test
==25862==
SubString is: BrownFox
==25862==
==25862== HEAP SUMMARY:
==25862== in use at exit: 0 bytes in 0 blocks
==25862== total heap usage: 1 allocs, 1 frees, 72 bytes allocated
==25862==
==25862== All heap blocks were freed -- no leaks are possible
==25862==
==25862== For counts of detected and suppressed errors, rerun with: -v
==25862== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
为什么我不能调用(分配)origstr 然后给它一些东西?如果我想分配那个变量,并在程序运行过程中将它作为另一个字符串变量的一部分,或者用它来捕获另一个函数的结果 returns 一个字符串怎么办?然后我是否必须像处理 newsubstr 一样处理它?
这让我有点困惑,有人可以解释一下它是如何工作的,以便我更好地理解它吗?
origstr = "TheQuickBrownFoxJumpedOverTheLazyDog";
通过这样做,您将更改为 origstr
指向的内容。此后 origstr
不指向 calloc
分配的内存块。
而您 free
内存未由 calloc
或类似函数分配,因此导致您的程序出错。
使用strcpy
复制字符串到origstr
-
strcpy(origstr,"TheQuickBrownFoxJumpedOverTheLazyDog");
然后你可以free
你的指针origstr
。
因为内存泄漏。你重新分配指针,它实际上是不正确的 free()
它是你拥有的。
要将内容复制到分配的指针,请使用 strcpy()
strcpy(origstr, "TheQuickBrownFoxJumpedOverTheLazyDog");
让我们看看如何:
你用calloc()
请求内存
origstring = calloc(9, sizeof(char*))
由于多种原因,这是错误的
- 您正在为
9
个指针分配 space,而不是 9
个字符。
- 你真的不需要
calloc()
因为你会立即覆盖内容,使用malloc()
。
你用字符串文字覆盖指针
origstr = "TheQuickBrownFoxJumpedOverTheLazyDog";
现在你失去了对指针的引用 return 之前 calloc()
并且你不可能 free()
它,你应该只 free()
指针 return通过 malloc()/calloc()/realloc()
.
事实是,你不需要calloc()
这个oristring
指针,calloc()
/malloc()
不用来让你赋值给一个指针, 但要写入指针指向的内存,或者更好的是,指向一些内存,你可以 read/write from/to.
通过将字符串文字分配给 origstr
,您 不会 复制字符串而只是更改 origstr
的值,从而丢失指向 calloc
。 free
ing origstr
现在会导致未定义的行为。
使用strcpy
或strncpy
来真正将字符串存储在堆上。但实际上为 origstr
删除 calloc
应该就足够了。
备注:
- 正如@LeeDanielCrocker 在对此答案的评论中提到的,您可能打算为
char
分配 space,而不是 char*
,从而减少分配内存的大小剧烈地。您应该将 sizeof(char*)
替换为 sizeof(char)
(a.k.a. 1
).
我正在尝试学习一些东西(作为一种爱好)并尝试学习使用 Valgrind。然而,这对我来说似乎没有意义。似乎 Valgrind 说当我在使用任何东西之前用 calloc 分配字节时,字节丢失了!有人可以解释这里发生了什么以及为什么第二个程序有效吗?我在 Eclipse 中以调试模式编译程序,并在调试可执行文件上编译 运行 Valgrind。
程序如下:
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4
5 int main(void) {
6
7 char* origstr = calloc(37, sizeof(char*));
8 char* newsubstr = calloc(9, sizeof(char*));
9
10 origstr = "TheQuickBrownFoxJumpedOverTheLazyDog";
11
12 strncpy(newsubstr, origstr + 8, 8);
13 printf("SubString is: %s\n", newsubstr);
14
15 free(newsubstr);
16 free(origstr);
17 return 0;
18 }
这是 Valgrind 给我的:
$ valgrind --tool=memcheck --leak-check=full ./test
==25404== Memcheck, a memory error detector
==25404== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==25404== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==25404== Command: ./test
==25404==
SubString is: BrownFox
==25404== Invalid free() / delete / delete[] / realloc()
==25404== at 0x4C29E90: free (vg_replace_malloc.c:473)
==25404== by 0x400665: main (test.c:16)
==25404== Address 0x4006f8 is not stack'd, malloc'd or (recently) free'd
==25404==
==25404==
==25404== HEAP SUMMARY:
==25404== in use at exit: 296 bytes in 1 blocks
==25404== total heap usage: 2 allocs, 2 frees, 368 bytes allocated
==25404==
==25404== 296 bytes in 1 blocks are definitely lost in loss record 1 of 1
==25404== at 0x4C2AD10: calloc (vg_replace_malloc.c:623)
==25404== by 0x4005FC: main (test.c:7)
==25404==
==25404== LEAK SUMMARY:
==25404== definitely lost: 296 bytes in 1 blocks
==25404== indirectly lost: 0 bytes in 0 blocks
==25404== possibly lost: 0 bytes in 0 blocks
==25404== still reachable: 0 bytes in 0 blocks
==25404== suppressed: 0 bytes in 0 blocks
==25404==
==25404== For counts of detected and suppressed errors, rerun with: -v
==25404== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
如果我删除两个 free() 语句,这就是 Valgrind 给我的:
$ valgrind --tool=memcheck --leak-check=full ./test
==25597== Memcheck, a memory error detector
==25597== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==25597== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==25597== Command: ./test
==25597==
SubString is: BrownFox
==25597==
==25597== HEAP SUMMARY:
==25597== in use at exit: 368 bytes in 2 blocks
==25597== total heap usage: 2 allocs, 0 frees, 368 bytes allocated
==25597==
==25597== 72 bytes in 1 blocks are definitely lost in loss record 1 of 2
==25597== at 0x4C2AD10: calloc (vg_replace_malloc.c:623)
==25597== by 0x4005BF: main (test.c:8)
==25597==
==25597== 296 bytes in 1 blocks are definitely lost in loss record 2 of 2
==25597== at 0x4C2AD10: calloc (vg_replace_malloc.c:623)
==25597== by 0x4005AC: main (test.c:7)
==25597==
==25597== LEAK SUMMARY:
==25597== definitely lost: 368 bytes in 2 blocks
==25597== indirectly lost: 0 bytes in 0 blocks
==25597== possibly lost: 0 bytes in 0 blocks
==25597== still reachable: 0 bytes in 0 blocks
==25597== suppressed: 0 bytes in 0 blocks
==25597==
==25597== For counts of detected and suppressed errors, rerun with: -v
==25597== ERROR SUMMARY: 2 errors from 2 contexts (suppressed: 0 from 0)
现在,如果我 运行 这个程序:
1 #include <stdlib.h>
2 #include <stdio.h>
3 #include <string.h>
4
5 int main(void) {
6
7 char* origstr;
8 char* newsubstr = calloc(9, sizeof(char*));
9
10 origstr = "TheQuickBrownFoxJumpedOverTheLazyDog";
11
12 strncpy(newsubstr, origstr + 8, 8);
13 printf("SubString is: %s\n", newsubstr);
14
15 free(newsubstr);
16
17 return 0;
18 }
说明一切正常:
$ valgrind --tool=memcheck --leak-check=full ./test
==25862== Memcheck, a memory error detector
==25862== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==25862== Using Valgrind-3.10.0 and LibVEX; rerun with -h for copyright info
==25862== Command: ./test
==25862==
SubString is: BrownFox
==25862==
==25862== HEAP SUMMARY:
==25862== in use at exit: 0 bytes in 0 blocks
==25862== total heap usage: 1 allocs, 1 frees, 72 bytes allocated
==25862==
==25862== All heap blocks were freed -- no leaks are possible
==25862==
==25862== For counts of detected and suppressed errors, rerun with: -v
==25862== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
为什么我不能调用(分配)origstr 然后给它一些东西?如果我想分配那个变量,并在程序运行过程中将它作为另一个字符串变量的一部分,或者用它来捕获另一个函数的结果 returns 一个字符串怎么办?然后我是否必须像处理 newsubstr 一样处理它?
这让我有点困惑,有人可以解释一下它是如何工作的,以便我更好地理解它吗?
origstr = "TheQuickBrownFoxJumpedOverTheLazyDog";
通过这样做,您将更改为 origstr
指向的内容。此后 origstr
不指向 calloc
分配的内存块。
而您 free
内存未由 calloc
或类似函数分配,因此导致您的程序出错。
使用strcpy
复制字符串到origstr
-
strcpy(origstr,"TheQuickBrownFoxJumpedOverTheLazyDog");
然后你可以free
你的指针origstr
。
因为内存泄漏。你重新分配指针,它实际上是不正确的 free()
它是你拥有的。
要将内容复制到分配的指针,请使用 strcpy()
strcpy(origstr, "TheQuickBrownFoxJumpedOverTheLazyDog");
让我们看看如何:
你用
请求内存calloc()
origstring = calloc(9, sizeof(char*))
由于多种原因,这是错误的
- 您正在为
9
个指针分配 space,而不是9
个字符。 - 你真的不需要
calloc()
因为你会立即覆盖内容,使用malloc()
。
- 您正在为
你用字符串文字覆盖指针
origstr = "TheQuickBrownFoxJumpedOverTheLazyDog";
现在你失去了对指针的引用 return 之前
calloc()
并且你不可能free()
它,你应该只free()
指针 return通过malloc()/calloc()/realloc()
.
事实是,你不需要calloc()
这个oristring
指针,calloc()
/malloc()
不用来让你赋值给一个指针, 但要写入指针指向的内存,或者更好的是,指向一些内存,你可以 read/write from/to.
通过将字符串文字分配给 origstr
,您 不会 复制字符串而只是更改 origstr
的值,从而丢失指向 calloc
。 free
ing origstr
现在会导致未定义的行为。
使用strcpy
或strncpy
来真正将字符串存储在堆上。但实际上为 origstr
删除 calloc
应该就足够了。
备注:
- 正如@LeeDanielCrocker 在对此答案的评论中提到的,您可能打算为
char
分配 space,而不是char*
,从而减少分配内存的大小剧烈地。您应该将sizeof(char*)
替换为sizeof(char)
(a.k.a.1
).