OS X 上的 GCC 分配了比预期更多的内存
GCC on OS X allocs more memory than expected
我正在使用 Mac OS X 10.11.4 和 Xcode 7.3,其中包含 gcc 编译器。我使用自制软件下载了 valgrind 3.11。当我 运行 我的 C 程序使用 valgrind 时,这是输出
==4297==
==4297== HEAP SUMMARY:
==4297== in use at exit: 30,208 bytes in 188 blocks
==4297== total heap usage: 265 allocs, 77 frees, 40,286 bytes allocated
==4297==
==4297== LEAK SUMMARY:
==4297== definitely lost: 0 bytes in 0 blocks
==4297== indirectly lost: 0 bytes in 0 blocks
==4297== possibly lost: 2,064 bytes in 1 blocks
==4297== still reachable: 4,096 bytes in 1 blocks
==4297== suppressed: 24,048 bytes in 186 blocks
==4297== Rerun with --leak-check=full to see details of leaked memory
==4297==
==4297== For counts of detected and suppressed errors, rerun with: -v
==4297== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
在整个程序中,我有2个mallocs和2个free,所以我不知道为什么有265个allocs和更少的frees。我向使用 ubuntu 的朋友寻求帮助,当他用他的 gcc 编译我的代码并用 valgrind 运行 编译程序时,它带回了 3 个分配和 3 个释放,所以一切都是正确的。我发现这可能发生在某些编译器库中,或者如果它们不是最新的,但我不知道如何在 OS X.
中更新它们
- 这是我的代码
main.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include "game.h"
int main(int argc, char** argv) {
GAME team1;
GAME team2;
int len = 0; //only for valgrind
if(argc == 2) {
char* word;
len = strlen(argv[1]) + 1;
word = (char*)malloc(sizeof(char)*(len));
strcpy(word, argv[1]);
team1.team_name = word;
len = strlen("Team 2") + 1;
word = (char*)malloc(sizeof(char)*(len));
strcpy(word, "Team 2");
team2.team_name = word;
} else if(argc == 3) {
char* word;
len = strlen(argv[1]) + 1;
word = (char*)malloc(sizeof(char)*(len));
strcpy(word, argv[1]);
team1.team_name = word;
len = strlen(argv[2]) + 1;
word = (char*)malloc(sizeof(char)*(len));
strcpy(word, argv[2]);
team2.team_name = word;
} else {
char* word;
len = strlen("Team 1") + 1;
word = (char*)malloc(sizeof(char)*(len));
strcpy(word, "Team 1");
team1.team_name = word;
len = strlen("Team 2") + 1;
word = (char*)malloc(sizeof(char)*(len));
strcpy(word, "Team 2");
team2.team_name = word;
}
int player1, player2, players_number;
do { //PVP or PVAI
printf("How many players will play this game? [1/2]: ");
scanf("%d", &players_number);
} while((players_number != 1) && (players_number != 2));
names(&team1, &team2); //add names
abilities(&team1, &team2); //add hp, def, att
render(&team1, &team2);
//choosing first players
printf("Choose player from Team 1: ");
scanf("%d", &player1);
while(getchar() != '\n')
;
if(players_number == 2){
printf("Choose player from Team 2: ");
scanf("%d", &player2);
while(getchar() != '\n')
;
} else { //If PVAI
srand(time(NULL));
player2 = rand() % 5 + 1;
printf("Choose player from Team 2: %d\n", player2);
}
/////////////////////////
do { //GAME
if(team1.hp[player1 - 1] == 0) {
printf("Choose player from Team 1: ");
scanf("%d", &player1);
while(getchar() != '\n')
;
}
if((team2.hp[player2 - 1] == 0) && (players_number == 2)) {
printf("Choose player from Team 2: ");
scanf("%d", &player2);
while(getchar() != '\n')
;
} else if(team2.hp[player2 - 1] == 0) { //If PVAI
do {
player2 = rand() % 5 + 1;
} while(team2.hp[player2 - 1] == 0);
printf("Choose players from Team 2: %d\n", player2);
}
printf("---------------------------\n");
battle(&team1, &team2, (player1 - 1), (player2 - 1));
render(&team1, &team2);
} while(who_wins(&team1, &team2) == 0);
printf("Team %d wins!\n", who_wins(&team1, &team2));
free(team1.team_name);
free(team2.team_name);
return 0;
}
game.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h> //for delay
#include <sys/stat.h> //for file size
#include "game.h"
void render(GAME *team1, GAME *team2) { //rendering the gaming table
printf("%s\tHP\tDEF\tATT\n", team1->team_name);
printf("---------------------------\n");
for(int i = 0; i <= 4; i++) {
printf("%s\t%d\t%d\t%d\n", team1->name[i], team1->hp[i], team1->def[i], team1->att[i]);
}
printf("---------------------------\n");
printf("%s\n", team2->team_name);
printf("---------------------------\n");
for(int i = 0; i <= 4; i++) {
printf("%s\t%d\t%d\t%d\n", team2->name[i], team2->hp[i], team2->def[i], team2->att[i]);
}
printf("---------------------------\n");
}
void names(GAME *team1, GAME *team2) { //choose random names from *.txt file
printf("Generating teams...\n");
FILE *fr = fopen("NAMES.txt", "r");
if(fr == NULL) {
printf("The file with names is not allowed, we will use pre-defined names for you.\n");
non_generated_names(&team1, &team2);
return; //can use exit instead of return and exit the program if names are not allowed
}
struct stat st;
stat("NAMES.txt", &st);
int size = st.st_size;
srand(time(NULL));
for(int i = 0; i <= 4; i++) {
fseek(fr, ((rand() % size) + 1), SEEK_SET);
if(fscanf(fr, "%*s\n%20s", team1->name[i]) == EOF)
i--;
}
for(int i = 0; i <= 4; i++) {
fseek(fr, ((rand() % size) + 1), SEEK_SET);
if(fscanf(fr, "%*s\n%20s", team2->name[i]) == EOF)
i--;
}
printf("Success!\n");
printf("---------------------------\n");
fclose(fr);
}
void non_generated_names(GAME **team1, GAME **team2) { //if *.txt file is not allowed, this is used for adding pre-defined names
for(int i = 0; i <= 4; i++) {
switch(i) {
case 0:
strcpy((*team1)->name[i], "Jack");
break;
case 1:
strcpy((*team1)->name[i], "Jim");
break;
case 2:
strcpy((*team1)->name[i], "John");
break;
case 3:
strcpy((*team1)->name[i], "Tom");
break;
case 4:
strcpy((*team1)->name[i], "Hank");
break;
}
}
for(int i = 0; i <= 4; i++) {
switch(i) {
case 0:
strcpy((*team2)->name[i], "Tim");
break;
case 1:
strcpy((*team2)->name[i], "Mark");
break;
case 2:
strcpy((*team2)->name[i], "Alf");
break;
case 3:
strcpy((*team2)->name[i], "Ted");
break;
case 4:
strcpy((*team2)->name[i], "Bil");
break;
}
}
}
void abilities(GAME *team1, GAME *team2) { //add HP, ATT and DEF to players
srand(time(NULL));
for(int i = 0; i <= 4; i++) {
team1->hp[i] = 5;
team2->hp[i] = 5;
team1->def[i] = rand() % 4 + 1;
team1->att[i] = 5 - team1->def[i];
team2->def[i] = rand() % 4 + 1;
team2->att[i] = 5 - team2->def[i];
}
}
int who_wins(GAME *team1, GAME *team2) { //tests if someone and who wins the game
int win = 2;
for(int i = 0; i <= 4; i++) {
if(team1->hp[i] != 0) {
win = 1;
break;
}
}
if(win == 2)
return 2;
for(int i = 0; i <= 4; i++) {
if(team2->hp[i] != 0) {
win = 0;
break;
}
}
if(win == 1)
return 1;
return 0;
}
void change_attacker(int *attacker) { //swap 1 and 2
if(*attacker == 1)
*attacker = 2;
else if(*attacker == 2)
*attacker = 1;
}
void battle(GAME *team1, GAME *team2, int player1, int player2) { //Battle engine
srand(time(NULL));
int attacker = rand() % 2 + 1; //random team to start
printf("Battle begins in few seconds...\n");
//sleep(1); //disabled delays for testing
if(attacker == 1) {
printf("%s will starts...\n", team1->team_name);
} else
printf("%s will starts...\n", team2->team_name);
//sleep(1);
printf("\n!!!START!!!\n\n");
printf("---------------------------\n");
while((team1->hp[player1] != 0) && (team2->hp[player2] != 0)) {
//sleep(1); //delay
if(attacker == 1) {
if((rand() % (team1->att[player1] + team2->def[player2]) + 1) > team2->def[player2]) {
team2->hp[player2]--;
printf("Attacker wins!\n");
if(team2->hp[player2] != 0)
printf("%s from %s has been hit, %d HP remaining.\n", team2->name[player2], team2->team_name, team2->hp[player2]);
else
printf("%s from %s is dead!\n", team2->name[player2], team2->team_name);
printf("---------------------------\n");
} else {
printf("Defender wins!\n");
printf("---------------------------\n");
}
} else if(attacker == 2) {
if((rand() % (team1->def[player1] + team2->att[player2]) + 1) > team1->def[player1]) {
team1->hp[player1]--;
printf("Attacker wins!\n");
if(team1->hp[player1] != 0)
printf("%s from %s has been hit, %d HP remaining.\n", team1->name[player1], team1->team_name, team1->hp[player1]);
else
printf("%s from %s is dead!\n", team1->name[player1], team1->team_name);
printf("---------------------------\n");
} else {
printf("Defender wins!\n");
printf("---------------------------\n");
}
}
change_attacker(&attacker);
}
}
您看到的大部分内容是 Mac OS X 上的 'normal'。C 启动代码在调用 main()
之前进行了大量内存分配,并且其中大部分未被释放。压制很重要。
创建这样的程序:
int main(void)
{
return 0;
}
和 运行 在我的 Mac OS X 10.11.4 机器 (GCC 6.1.0) 上运行它产生:
==58367== Memcheck, a memory error detector
==58367== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==58367== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info
==58367== Command: ./xx
==58367==
==58367==
==58367== HEAP SUMMARY:
==58367== in use at exit: 22,233 bytes in 186 blocks
==58367== total heap usage: 270 allocs, 84 frees, 28,465 bytes allocated
==58367==
==58367== LEAK SUMMARY:
==58367== definitely lost: 0 bytes in 0 blocks
==58367== indirectly lost: 0 bytes in 0 blocks
==58367== possibly lost: 0 bytes in 0 blocks
==58367== still reachable: 0 bytes in 0 blocks
==58367== suppressed: 22,233 bytes in 186 blocks
==58367==
==58367== For counts of detected and suppressed errors, rerun with: -v
==58367== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
我用 XCode 的 clang
编译得到了类似的结果。 -v
选项嘈杂但信息丰富。
所有内存分配都是例行公事,不值得担心。
在 valgrind
的输出中,您有一些可能丢失的内存和一些仍然可用的内存。您应该进一步探索以找出它们是什么。 --leak-check=full
选项会有所帮助。您最终可能也会使用 --gen-suppressions
选项(valgrind --help
探索可用的选项),然后在重新 运行 时使用 --suppressions=your-suppressions-file
。
我有一个文件,里面有 22 个抑制,我有时需要使用它。我曾经有更多的抑制,但 valgrind
在自动执行它们方面做得更好。保持 valgrind
最新通常也是一个好主意;在 Mac OS X 升级后重建是个好主意。
How I can check my program if OS X allocs memory by itself?
leak13.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char *s = malloc(33);
strcpy(s, "Adjudication");
printf("[%s]\n", s);
/* free(s); // leak! */
return 0;
}
运行 valgrind
$ valgrind --leak-check=full leak13
==2301== Memcheck, a memory error detector
==2301== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==2301== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info
==2301== Command: leak13
==2301==
[Adjudication]
==2301==
==2301== HEAP SUMMARY:
==2301== in use at exit: 26,362 bytes in 188 blocks
==2301== total heap usage: 272 allocs, 84 frees, 32,594 bytes allocated
==2301==
==2301== 33 bytes in 1 blocks are definitely lost in loss record 24 of 65
==2301== at 0x100007CF1: malloc (vg_replace_malloc.c:302)
==2301== by 0x100000F4D: main (leak13.c:7)
==2301==
==2301== LEAK SUMMARY:
==2301== definitely lost: 33 bytes in 1 blocks
==2301== indirectly lost: 0 bytes in 0 blocks
==2301== possibly lost: 0 bytes in 0 blocks
==2301== still reachable: 0 bytes in 0 blocks
==2301== suppressed: 26,329 bytes in 187 blocks
==2301==
==2301== For counts of detected and suppressed errors, rerun with: -v
==2301== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 18 from 18)
$
这里,很明显有一个泄漏,来自源代码第 7 行的 malloc()
。 (这是 Mac OS X 10.11.5 上的 运行,升级后没有重建 valgrind
或 gcc
。这似乎并不重要这一次。)
当您在 Linux 上 运行 一个程序时,您可以获得完全干净的健康证明。
例如,在 Ubuntu 14.04 LTS 上,除了 free
未注释掉之外,代码如上,我得到了输出:
$ valgrind ./noleak13
==38142== Memcheck, a memory error detector
==38142== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==38142== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==38142== Command: ./noleak13
==38142==
[Adjudication]
==38142==
==38142== HEAP SUMMARY:
==38142== in use at exit: 0 bytes in 0 blocks
==38142== total heap usage: 1 allocs, 1 frees, 33 bytes allocated
==38142==
==38142== All heap blocks were freed -- no leaks are possible
==38142==
==38142== For counts of detected and suppressed errors, rerun with: -v
==38142== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
$
您不会在 Mac OS X 上看到 'All heap blocks were free — no leaks are possible' 消息,但您可以丢失 0 个字节、间接丢失 0 个字节、可能丢失 0 个字节以及仍然丢失 0 个字节可达——除了被隐藏的项目——这是最好的。
我正在使用 Mac OS X 10.11.4 和 Xcode 7.3,其中包含 gcc 编译器。我使用自制软件下载了 valgrind 3.11。当我 运行 我的 C 程序使用 valgrind 时,这是输出
==4297==
==4297== HEAP SUMMARY:
==4297== in use at exit: 30,208 bytes in 188 blocks
==4297== total heap usage: 265 allocs, 77 frees, 40,286 bytes allocated
==4297==
==4297== LEAK SUMMARY:
==4297== definitely lost: 0 bytes in 0 blocks
==4297== indirectly lost: 0 bytes in 0 blocks
==4297== possibly lost: 2,064 bytes in 1 blocks
==4297== still reachable: 4,096 bytes in 1 blocks
==4297== suppressed: 24,048 bytes in 186 blocks
==4297== Rerun with --leak-check=full to see details of leaked memory
==4297==
==4297== For counts of detected and suppressed errors, rerun with: -v
==4297== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
在整个程序中,我有2个mallocs和2个free,所以我不知道为什么有265个allocs和更少的frees。我向使用 ubuntu 的朋友寻求帮助,当他用他的 gcc 编译我的代码并用 valgrind 运行 编译程序时,它带回了 3 个分配和 3 个释放,所以一切都是正确的。我发现这可能发生在某些编译器库中,或者如果它们不是最新的,但我不知道如何在 OS X.
中更新它们- 这是我的代码
main.c
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include "game.h"
int main(int argc, char** argv) {
GAME team1;
GAME team2;
int len = 0; //only for valgrind
if(argc == 2) {
char* word;
len = strlen(argv[1]) + 1;
word = (char*)malloc(sizeof(char)*(len));
strcpy(word, argv[1]);
team1.team_name = word;
len = strlen("Team 2") + 1;
word = (char*)malloc(sizeof(char)*(len));
strcpy(word, "Team 2");
team2.team_name = word;
} else if(argc == 3) {
char* word;
len = strlen(argv[1]) + 1;
word = (char*)malloc(sizeof(char)*(len));
strcpy(word, argv[1]);
team1.team_name = word;
len = strlen(argv[2]) + 1;
word = (char*)malloc(sizeof(char)*(len));
strcpy(word, argv[2]);
team2.team_name = word;
} else {
char* word;
len = strlen("Team 1") + 1;
word = (char*)malloc(sizeof(char)*(len));
strcpy(word, "Team 1");
team1.team_name = word;
len = strlen("Team 2") + 1;
word = (char*)malloc(sizeof(char)*(len));
strcpy(word, "Team 2");
team2.team_name = word;
}
int player1, player2, players_number;
do { //PVP or PVAI
printf("How many players will play this game? [1/2]: ");
scanf("%d", &players_number);
} while((players_number != 1) && (players_number != 2));
names(&team1, &team2); //add names
abilities(&team1, &team2); //add hp, def, att
render(&team1, &team2);
//choosing first players
printf("Choose player from Team 1: ");
scanf("%d", &player1);
while(getchar() != '\n')
;
if(players_number == 2){
printf("Choose player from Team 2: ");
scanf("%d", &player2);
while(getchar() != '\n')
;
} else { //If PVAI
srand(time(NULL));
player2 = rand() % 5 + 1;
printf("Choose player from Team 2: %d\n", player2);
}
/////////////////////////
do { //GAME
if(team1.hp[player1 - 1] == 0) {
printf("Choose player from Team 1: ");
scanf("%d", &player1);
while(getchar() != '\n')
;
}
if((team2.hp[player2 - 1] == 0) && (players_number == 2)) {
printf("Choose player from Team 2: ");
scanf("%d", &player2);
while(getchar() != '\n')
;
} else if(team2.hp[player2 - 1] == 0) { //If PVAI
do {
player2 = rand() % 5 + 1;
} while(team2.hp[player2 - 1] == 0);
printf("Choose players from Team 2: %d\n", player2);
}
printf("---------------------------\n");
battle(&team1, &team2, (player1 - 1), (player2 - 1));
render(&team1, &team2);
} while(who_wins(&team1, &team2) == 0);
printf("Team %d wins!\n", who_wins(&team1, &team2));
free(team1.team_name);
free(team2.team_name);
return 0;
}
game.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include <unistd.h> //for delay
#include <sys/stat.h> //for file size
#include "game.h"
void render(GAME *team1, GAME *team2) { //rendering the gaming table
printf("%s\tHP\tDEF\tATT\n", team1->team_name);
printf("---------------------------\n");
for(int i = 0; i <= 4; i++) {
printf("%s\t%d\t%d\t%d\n", team1->name[i], team1->hp[i], team1->def[i], team1->att[i]);
}
printf("---------------------------\n");
printf("%s\n", team2->team_name);
printf("---------------------------\n");
for(int i = 0; i <= 4; i++) {
printf("%s\t%d\t%d\t%d\n", team2->name[i], team2->hp[i], team2->def[i], team2->att[i]);
}
printf("---------------------------\n");
}
void names(GAME *team1, GAME *team2) { //choose random names from *.txt file
printf("Generating teams...\n");
FILE *fr = fopen("NAMES.txt", "r");
if(fr == NULL) {
printf("The file with names is not allowed, we will use pre-defined names for you.\n");
non_generated_names(&team1, &team2);
return; //can use exit instead of return and exit the program if names are not allowed
}
struct stat st;
stat("NAMES.txt", &st);
int size = st.st_size;
srand(time(NULL));
for(int i = 0; i <= 4; i++) {
fseek(fr, ((rand() % size) + 1), SEEK_SET);
if(fscanf(fr, "%*s\n%20s", team1->name[i]) == EOF)
i--;
}
for(int i = 0; i <= 4; i++) {
fseek(fr, ((rand() % size) + 1), SEEK_SET);
if(fscanf(fr, "%*s\n%20s", team2->name[i]) == EOF)
i--;
}
printf("Success!\n");
printf("---------------------------\n");
fclose(fr);
}
void non_generated_names(GAME **team1, GAME **team2) { //if *.txt file is not allowed, this is used for adding pre-defined names
for(int i = 0; i <= 4; i++) {
switch(i) {
case 0:
strcpy((*team1)->name[i], "Jack");
break;
case 1:
strcpy((*team1)->name[i], "Jim");
break;
case 2:
strcpy((*team1)->name[i], "John");
break;
case 3:
strcpy((*team1)->name[i], "Tom");
break;
case 4:
strcpy((*team1)->name[i], "Hank");
break;
}
}
for(int i = 0; i <= 4; i++) {
switch(i) {
case 0:
strcpy((*team2)->name[i], "Tim");
break;
case 1:
strcpy((*team2)->name[i], "Mark");
break;
case 2:
strcpy((*team2)->name[i], "Alf");
break;
case 3:
strcpy((*team2)->name[i], "Ted");
break;
case 4:
strcpy((*team2)->name[i], "Bil");
break;
}
}
}
void abilities(GAME *team1, GAME *team2) { //add HP, ATT and DEF to players
srand(time(NULL));
for(int i = 0; i <= 4; i++) {
team1->hp[i] = 5;
team2->hp[i] = 5;
team1->def[i] = rand() % 4 + 1;
team1->att[i] = 5 - team1->def[i];
team2->def[i] = rand() % 4 + 1;
team2->att[i] = 5 - team2->def[i];
}
}
int who_wins(GAME *team1, GAME *team2) { //tests if someone and who wins the game
int win = 2;
for(int i = 0; i <= 4; i++) {
if(team1->hp[i] != 0) {
win = 1;
break;
}
}
if(win == 2)
return 2;
for(int i = 0; i <= 4; i++) {
if(team2->hp[i] != 0) {
win = 0;
break;
}
}
if(win == 1)
return 1;
return 0;
}
void change_attacker(int *attacker) { //swap 1 and 2
if(*attacker == 1)
*attacker = 2;
else if(*attacker == 2)
*attacker = 1;
}
void battle(GAME *team1, GAME *team2, int player1, int player2) { //Battle engine
srand(time(NULL));
int attacker = rand() % 2 + 1; //random team to start
printf("Battle begins in few seconds...\n");
//sleep(1); //disabled delays for testing
if(attacker == 1) {
printf("%s will starts...\n", team1->team_name);
} else
printf("%s will starts...\n", team2->team_name);
//sleep(1);
printf("\n!!!START!!!\n\n");
printf("---------------------------\n");
while((team1->hp[player1] != 0) && (team2->hp[player2] != 0)) {
//sleep(1); //delay
if(attacker == 1) {
if((rand() % (team1->att[player1] + team2->def[player2]) + 1) > team2->def[player2]) {
team2->hp[player2]--;
printf("Attacker wins!\n");
if(team2->hp[player2] != 0)
printf("%s from %s has been hit, %d HP remaining.\n", team2->name[player2], team2->team_name, team2->hp[player2]);
else
printf("%s from %s is dead!\n", team2->name[player2], team2->team_name);
printf("---------------------------\n");
} else {
printf("Defender wins!\n");
printf("---------------------------\n");
}
} else if(attacker == 2) {
if((rand() % (team1->def[player1] + team2->att[player2]) + 1) > team1->def[player1]) {
team1->hp[player1]--;
printf("Attacker wins!\n");
if(team1->hp[player1] != 0)
printf("%s from %s has been hit, %d HP remaining.\n", team1->name[player1], team1->team_name, team1->hp[player1]);
else
printf("%s from %s is dead!\n", team1->name[player1], team1->team_name);
printf("---------------------------\n");
} else {
printf("Defender wins!\n");
printf("---------------------------\n");
}
}
change_attacker(&attacker);
}
}
您看到的大部分内容是 Mac OS X 上的 'normal'。C 启动代码在调用 main()
之前进行了大量内存分配,并且其中大部分未被释放。压制很重要。
创建这样的程序:
int main(void)
{
return 0;
}
和 运行 在我的 Mac OS X 10.11.4 机器 (GCC 6.1.0) 上运行它产生:
==58367== Memcheck, a memory error detector
==58367== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==58367== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info
==58367== Command: ./xx
==58367==
==58367==
==58367== HEAP SUMMARY:
==58367== in use at exit: 22,233 bytes in 186 blocks
==58367== total heap usage: 270 allocs, 84 frees, 28,465 bytes allocated
==58367==
==58367== LEAK SUMMARY:
==58367== definitely lost: 0 bytes in 0 blocks
==58367== indirectly lost: 0 bytes in 0 blocks
==58367== possibly lost: 0 bytes in 0 blocks
==58367== still reachable: 0 bytes in 0 blocks
==58367== suppressed: 22,233 bytes in 186 blocks
==58367==
==58367== For counts of detected and suppressed errors, rerun with: -v
==58367== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
我用 XCode 的 clang
编译得到了类似的结果。 -v
选项嘈杂但信息丰富。
所有内存分配都是例行公事,不值得担心。
在 valgrind
的输出中,您有一些可能丢失的内存和一些仍然可用的内存。您应该进一步探索以找出它们是什么。 --leak-check=full
选项会有所帮助。您最终可能也会使用 --gen-suppressions
选项(valgrind --help
探索可用的选项),然后在重新 运行 时使用 --suppressions=your-suppressions-file
。
我有一个文件,里面有 22 个抑制,我有时需要使用它。我曾经有更多的抑制,但 valgrind
在自动执行它们方面做得更好。保持 valgrind
最新通常也是一个好主意;在 Mac OS X 升级后重建是个好主意。
How I can check my program if OS X allocs memory by itself?
leak13.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void)
{
char *s = malloc(33);
strcpy(s, "Adjudication");
printf("[%s]\n", s);
/* free(s); // leak! */
return 0;
}
运行 valgrind
$ valgrind --leak-check=full leak13
==2301== Memcheck, a memory error detector
==2301== Copyright (C) 2002-2015, and GNU GPL'd, by Julian Seward et al.
==2301== Using Valgrind-3.12.0.SVN and LibVEX; rerun with -h for copyright info
==2301== Command: leak13
==2301==
[Adjudication]
==2301==
==2301== HEAP SUMMARY:
==2301== in use at exit: 26,362 bytes in 188 blocks
==2301== total heap usage: 272 allocs, 84 frees, 32,594 bytes allocated
==2301==
==2301== 33 bytes in 1 blocks are definitely lost in loss record 24 of 65
==2301== at 0x100007CF1: malloc (vg_replace_malloc.c:302)
==2301== by 0x100000F4D: main (leak13.c:7)
==2301==
==2301== LEAK SUMMARY:
==2301== definitely lost: 33 bytes in 1 blocks
==2301== indirectly lost: 0 bytes in 0 blocks
==2301== possibly lost: 0 bytes in 0 blocks
==2301== still reachable: 0 bytes in 0 blocks
==2301== suppressed: 26,329 bytes in 187 blocks
==2301==
==2301== For counts of detected and suppressed errors, rerun with: -v
==2301== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 18 from 18)
$
这里,很明显有一个泄漏,来自源代码第 7 行的 malloc()
。 (这是 Mac OS X 10.11.5 上的 运行,升级后没有重建 valgrind
或 gcc
。这似乎并不重要这一次。)
当您在 Linux 上 运行 一个程序时,您可以获得完全干净的健康证明。
例如,在 Ubuntu 14.04 LTS 上,除了 free
未注释掉之外,代码如上,我得到了输出:
$ valgrind ./noleak13
==38142== Memcheck, a memory error detector
==38142== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al.
==38142== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info
==38142== Command: ./noleak13
==38142==
[Adjudication]
==38142==
==38142== HEAP SUMMARY:
==38142== in use at exit: 0 bytes in 0 blocks
==38142== total heap usage: 1 allocs, 1 frees, 33 bytes allocated
==38142==
==38142== All heap blocks were freed -- no leaks are possible
==38142==
==38142== For counts of detected and suppressed errors, rerun with: -v
==38142== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)
$
您不会在 Mac OS X 上看到 'All heap blocks were free — no leaks are possible' 消息,但您可以丢失 0 个字节、间接丢失 0 个字节、可能丢失 0 个字节以及仍然丢失 0 个字节可达——除了被隐藏的项目——这是最好的。