GCC在OS X allocs更多的内存比预期 [英] GCC on OS X allocs more memory than expected
问题描述
我使用的是Mac OS X 10.11.4使用X code 7.3在它的gcc编译器。我下载的valgrind 3.11使用自制。当我运行我的C程序的valgrind用,这是输出
== == 4297
== == 4297 HEAP摘要:
== == 4297使用在出口处:在188块30,208字节
== == 4297总堆的使用情况:265 allocs,77的FreeS,40286字节分配
== == 4297
== == 4297泄漏摘要:
== == 4297肯定丢失:0字节0块
== == 4297失去了间接:0字节0块
== == 4297可能丢失:2064字节1块
== == 4297仍可达:在1块4,096字节
== == 4297燮pressed:24048字节186块
== == 4297与重新运行--leak检查=全看到内存泄露的细节
== == 4297
== == 4297对于检测燮pressed错误计数,重新运行:-v
== == 4297错误摘要:从0 0上下文错误(SUP pressed:0 0)
在整个程序中,我有2个mallocs和2的FreeS,所以我不知道为什么有265 allocs和更少的FreeS。我问我的朋友谁使用Ubuntu的一个帮助,当他编译我的code。与他的gcc和Valgrind的运行程序,它带回3 allocs和3的FreeS,所以一切是正确的。我发现,这可能会在一些编译器库发生,或者如果他们没有及时更新,但我不知道如何在OS X更新。
- 这是我的code
的main.c
的#include<&stdio.h中GT;
#包括LT&;&stdlib.h中GT;
#包括LT&;&time.h中GT;
#包括LT&;&string.h中GT;#包括game.hINT主(INT ARGC,字符** argv的){ GAME TEAM1;
GAME TEAM2; INT LEN = 0; //只为的valgrind 如果(的argc == 2){
字符*字; LEN = strlen的(的argv [1])+ 1; 字=(字符*)malloc的(的sizeof(字符)*(LEN));
的strcpy(文字,ARGV [1]);
team1.team_name =字; LEN = strlen的(团队2)+ 1; 字=(字符*)malloc的(的sizeof(字符)*(LEN));
的strcpy(字,团队2);
team2.team_name =字; }否则如果(argc个== 3){
字符*字; LEN = strlen的(的argv [1])+ 1; 字=(字符*)malloc的(的sizeof(字符)*(LEN));
的strcpy(文字,ARGV [1]);
team1.team_name =字; LEN = strlen的(的argv [2])+ 1; 字=(字符*)malloc的(的sizeof(字符)*(LEN));
的strcpy(字,的argv [2]);
team2.team_name =字; }其他{
字符*字; LEN = strlen的(团队1)+ 1; 字=(字符*)malloc的(的sizeof(字符)*(LEN));
的strcpy(字,团队1);
team1.team_name =字; LEN = strlen的(团队2)+ 1; 字=(字符*)malloc的(的sizeof(字符)*(LEN));
的strcpy(字,团队2);
team2.team_name =字;
} INT PLAYER1,player2,players_number; 做{// PVP或PVAI
的printf(有多少玩家会玩这个游戏[1/2]:);
scanf函数(%d个,&安培; players_number);
}而((players_number = 1)及!及(players_number = 2)!); 名字(安培; TEAM1,&安培; TEAM2); //添加名称
能力(安培; TEAM1,&安培; TEAM2); //添加马力,闪避,ATT 渲染(安培; TEAM1,&安培; TEAM2); //第一选择的球员
的printf(从1队选择球员:);
scanf函数(%d个,&安培; PLAYER1); 而(的getchar()!='\\ n')
; 如果(players_number == 2){
的printf(从二队球员中选择:);
scanf函数(%d个,&安培; player2); 而(的getchar()!='\\ n')
;
}其他{//如果PVAI
函数srand(时间(NULL));
player2 =兰特()%5 + 1;
的printf(请从二队球员数:%d \\ n,player2);
}
///////////////////////// 做{// GAME
如果(team1.hp [PLAYER1 - 1] == 0){
的printf(从1队选择球员:);
scanf函数(%d个,&安培; PLAYER1); 而(的getchar()!='\\ n')
;
} 如果((team2.hp [player2 - 1] == 0)及及(players_number == 2)){
的printf(从二队球员中选择:);
scanf函数(%d个,&安培; player2); 而(的getchar()!='\\ n')
;
}否则如果(team2.hp [player2 - 1] == 0){//如果PVAI 做{
player2 =兰特()%5 + 1;
}而(team2.hp [player2 - 1] == 0); 的printf(从二队球员中选择:%d个\\ N,player2);
} 的printf(--------------------------- \\ n); 战斗(安培; TEAM1,&安培; TEAM2,(PLAYER1 - 1),(player2 - 1)); 渲染(安培; TEAM1,&安培; TEAM2); }而(who_wins(安培; TEAM1,&安培; TEAM2)== 0); 的printf(团队%d个胜\\ n!,who_wins(安培; TEAM1,&安培; TEAM2)); 免费(team1.team_name);
免费(team2.team_name); 返回0;
}
game.c
的#include<&stdio.h中GT;
#包括LT&;&stdlib.h中GT;
#包括LT&;&string.h中GT;
#包括LT&;&time.h中GT;
#包括LT&;&unistd.h中GT; //延迟
#包括LT&; SYS / stat.h> //文件大小#包括game.h无效渲染(GAME * TEAM1,GAME * TEAM2){//渲染游戏桌 的printf(%S \\ THP \\ TDEF \\ TATT \\ n,team1-> TEAM_NAME);
的printf(--------------------------- \\ n); 的for(int i = 0; I< = 4;我++){
的printf(%S \\ t%d个\\ t%d个\\ t%d个\\ N,team1->名[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;我++){
的printf(%S \\ t%d个\\ t%d个\\ t%d个\\ N,team2->名[I],team2-> HP [I],team2-> DEF [I],team2- > ATT [I]);
} 的printf(--------------------------- \\ n);}无效名称(GAME * TEAM1,GAME * TEAM2){//选择*。txt文件随机名称
的printf(生成团队... \\ n);
FILE * FR =的fopen(names.txt中,R);
如果(FR == NULL){
输出(与名称的文件是不允许的,我们将使用pre-定义的名称为您\\ n);
non_generated_names(安培; TEAM1,&安培; TEAM2);
返回; //可以使用,而不是返回退出和退出程序,如果名称不准
} struct stat中ST;
STAT(names.txt中,&安培; ST);
INT大小= st.st_size; 函数srand(时间(NULL)); 的for(int i = 0; I< = 4;我++){
fseek的(FR,((兰特()%的大小)+ 1),SEEK_SET);
如果(的fscanf(FR,%* S \\ N%20多岁,team1->名称由[i])== EOF)
一世 - ;
} 的for(int i = 0; I< = 4;我++){
fseek的(FR,((兰特()%的大小)+ 1),SEEK_SET);
如果(的fscanf(FR,%* S \\ N%20多岁,team2->名称由[i])== EOF)
一世 - ;
} 的printf(成功\\ n!);
的printf(--------------------------- \\ n);
FCLOSE(FR);
}无效non_generated_names(GAME ** TEAM1,GAME ** TEAM2){//如果不允许* .txt文件,这是用于添加pre-定义的名称 的for(int i = 0; I< = 4;我++){
开关(ⅰ){
情况下0:
的strcpy((* TEAM1) - GT;名[I],杰克);
打破;
情况1:
的strcpy((* TEAM1) - GT;名[I],吉姆);
打破;
案例2:
的strcpy((* TEAM1) - GT;名[I],约翰);
打破;
案例3:
的strcpy((* TEAM1) - GT;名[I],汤姆);
打破;
情况4:
的strcpy((* TEAM1) - >名由[i],汉克);
打破;
}
} 的for(int i = 0; I< = 4;我++){
开关(ⅰ){
情况下0:
的strcpy((* TEAM2) - GT;名[I],蒂姆);
打破;
情况1:
的strcpy((* TEAM2) - GT;名[I],马克);
打破;
案例2:
的strcpy((* TEAM2) - >名称[I]中,阿尔夫);
打破;
案例3:
的strcpy((* TEAM2) - GT;名[I],泰德);
打破;
情况4:
的strcpy((* TEAM2) - GT;名[I],胆红素);
打破;
}
}
}无效的能力(GAME * TEAM1,GAME * TEAM2){//添加HP,AT&T和DEF玩家 函数srand(时间(NULL)); 的for(int i = 0; I< = 4;我++){ team1-> HP [I] = 5;
team2-> HP [I] = 5; team1-> DEF [I] =兰特()%4 + 1;
team1-> ATT [i] = 5 - team1-> DEF [I]
team2-> DEF [I] =兰特()%4 + 1;
team2-> ATT [i] = 5 - team2-> DEF [I] }
}INT who_wins(GAME * TEAM1,GAME * TEAM2){//测试,如果有人,谁赢得了比赛
INT赢= 2; 的for(int i = 0; I< = 4;我++){
如果(team1->马力[I]!= 0){
赢= 1;
打破;
}
} 如果(胜利== 2)
返回2; 的for(int i = 0; I< = 4;我++){
如果(team2->马力[I]!= 0){
赢= 0;
打破;
}
} 如果(胜利== 1)
返回1; 返回0;
}无效change_attacker为(int *攻击者){//交换1和2 如果(*攻击者== 1)
*攻击= 2;
否则如果(*攻击者== 2)
*攻击= 1;}无效的战斗(GAME * TEAM1,GAME * TEAM2,诠释PLAYER1,诠释player2){//引擎之战 函数srand(时间(NULL));
INT攻击=兰特()%2 + 1; //随机组队开始 的printf(战斗开始在几秒钟内...... \\ n);
//睡眠(1); //测试禁用延迟
如果(攻击者== 1){
的printf(%s将启动... \\ n,team1-> TEAM_NAME);
}其他
的printf(%s将启动... \\ n,team2-> TEAM_NAME); //睡眠(1);
的printf(\\ n !!! START!\\ n \\ n);
的printf(--------------------------- \\ n); 而((team1->马力[PLAYER1] = 0)及!及(team2->!马力[player2] = 0)){ //睡眠(1); //延迟 如果(攻击者== 1){
如果((兰特()%(team1-> ATT [PLAYER1] + team2-> DEF [player2])+ 1)GT; team2-> DEF [player2]){
team2->惠普[player2] - ;
的printf(攻击者胜\\ n!);
如果(team2->!马力[player2] = 0)
的printf(%S%s的一直打到,%D HP剩余\\ n,team2->名[player2] team2-> TEAM_NAME,team2->惠普[player2]);
其他
的printf(%S%s的死\\ n!,team2->名[player2] team2-> TEAM_NAME);
的printf(--------------------------- \\ n);
}其他{
的printf(后卫赢得\\ n!);
的printf(--------------------------- \\ n);
}
}否则如果(攻击者== 2){
如果((兰特()%(team1-> DEF [PLAYER1] + team2-> ATT [player2])+ 1)GT; team1-> DEF [PLAYER1]){
team1->惠普[PLAYER1] - ;
的printf(攻击者胜\\ n!);
如果(team1->!马力[PLAYER1] = 0)
的printf(%S%s的一直打到,%D HP剩余\\ n,team1->名[PLAYER1] team1-> TEAM_NAME,team1->惠普[PLAYER1]);
其他
的printf(%S%s的死\\ n!,team1->名[PLAYER1] team1-> TEAM_NAME);
的printf(--------------------------- \\ n);
}其他{
的printf(后卫赢得\\ n!);
的printf(--------------------------- \\ n);
}
} change_attacker(安培;攻击者);
}
}
大多数时候,你所看到的是Mac OS X上的C启动code'正常'做了很多的内存分配之前调用的main()
,而且大部分不会释放。该SUP pressions是很重要的。
创建一个程序是这样的:
INT主要(无效)
{
返回0;
}
和我的Mac OS X 10.11.4机器上运行它(GCC 6.1.0)收益率:
== == 58367 MEMCHECK,内存错误检测
== == 58367版权所有(C)2002 - 2015年和GNU GPL的,Julian Seward写等。
== == 58367 Valgrind的使用,3.12.0.SVN和LibVEX;与-h版权信息重新运行
== == 58367命令:./xx
== == 58367
== == 58367
== == 58367 HEAP摘要:
== == 58367在退出,使用:22233 186块字节
== == 58367总堆的使用情况:270 allocs,84的FreeS,28465字节分配
== == 58367
== == 58367泄漏摘要:
== == 58367失去了肯定:0字节0块
== == 58367间接丧失:0字节0块
== == 58367失去了可能:0字节0块
== == 58367尚能访问:0块0字节
== == 58367燮pressed:22233字节186块
== == 58367
== == 58367侦测到并SUP pressed错误计数,重新运行:-v
== == 58367错误摘要:从0 0上下文错误(SUP pressed:0 0)
我得到了类似的结果与铛
从X code编译中。在 -v
选项嘈杂,但内容丰富。
所有的内存分配是家常便饭,而不是它是值得担忧的。
在从的valgrind
您的输出,你有可能失去的,有些还访问内存。你应该进一步探索,找出那些是什么。在 - 泄漏检查=全
选项会有所帮助。你可能最终会使用 - 根燮pressions
选项太(的valgrind --help
探索可用的选项),然后 - SUP pressions =您燮pressions文件重新运行时,
我在它22 SUP pressions,我有时需要使用的文件。我以前有更多的SUP pressions,但的valgrind
已得到在自动做他们更好。保持的valgrind
电流一般是一个好主意太;在Mac OS X升级后的重建是一个好主意。
我怎么可以自己检查我的计划,如果OS X allocs内存?
块引用>
leak13.c
的#include<&stdio.h中GT;
#包括LT&;&stdlib.h中GT;
#包括LT&;&string.h中GT;INT主要(无效)
{
字符* S =的malloc(33);
的strcpy(S,审判);
的printf([%S] \\ N,S);
/ *自由(S); // 泄漏! * /
返回0;
}与Valgrind的运行
$的valgrind --leak检查=全leak13
== == 2301 MEMCHECK,内存错误检测
== == 2301版权所有(C)2002 - 2015年和GNU GPL的,Julian Seward写等。
== == 2301 Valgrind的使用,3.12.0.SVN和LibVEX;与-h版权信息重新运行
== == 2301命令:leak13
== == 2301
[裁决]
== == 2301
== == 2301 HEAP摘要:
== == 2301使用在出口处:在188块26362字节
== == 2301总堆的使用情况:272 allocs,84的FreeS,32594字节分配
== == 2301
== == 2301年33合1块字节肯定是失去了在负的战绩65 24
== == 2301在0x100007CF1:的malloc(vg_replace_malloc.c:302)
== == 2301通过0x100000F4D:主(leak13.c:7)
== == 2301
== == 2301泄漏摘要:
== == 2301肯定失去了33个字节的块1
== == 2301失去了间接:0字节0块
== == 2301可能丢失:0字节0块
== == 2301到达尚:0块0字节
== == 2301燮pressed:26329字节187块
== == 2301
== == 2301对于检测燮pressed错误计数,重新运行:-v
== == 2301错误摘要:从1上下文1错误(SUP pressed:18 18)
$在这里,有明确的一个渗漏,从
的malloc()
在源$ C $ C线7。 (这是在Mac OS X 10.11.5而不必重建运行的valgrind
或GCC
自升级。一点也没有'T似乎要紧围绕这个时候。)在Linux上运行一个程序,你可以得到健康的彻底清洁提单。
例如,在Ubuntu 14.04 LTS,用code如上除了免费
被注释掉了,我得到的输出:$的valgrind ./noleak13
== == 38142 MEMCHECK,内存错误检测
== == 38142版权所有(C)2002至13年,和GNU GPL的,Julian Seward写等。
== == 38142 Valgrind的使用-3.10.1和LibVEX;与-h版权信息重新运行
== == 38142命令:./noleak13
== == 38142
[裁决]
== == 38142
== == 38142 HEAP摘要:
== == 38142在退出,使用:0块0字节
== == 38142总堆的使用情况:1 allocs,1的FreeS,33字节分配
== == 38142
== == 38142所有堆块被释放 - 无泄漏是可能的
== == 38142
== == 38142侦测到并SUP pressed错误计数,重新运行:-v
== == 38142错误摘要:从0 0上下文错误(SUP pressed:0 0)
$您不会看到所有堆块是自由 - 没有泄漏是可能的Mac OS X上的消息,但可以为0字节丢失,0字节间接丢失,0字节可能丢失,0字节仍可达 - 除了从SUP pressed项目 - 这是因为它得到
一样好。I am using Mac OS X 10.11.4 with Xcode 7.3 with gcc compiler in it. I downloaded valgrind 3.11 using homebrew. When I run my C program with valgrind, this is the output
==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)
In the whole program, I have 2 mallocs and 2 frees, so I have no idea why there are 265 allocs and fewer frees. I asked my friend who uses ubuntu for a help, and when he compiles my code with his gcc and run the program with valgrind, it brought back 3 allocs and 3 frees, so everything was correct. I found that this could happen in some compiler libraries, or if they are not up-to-date, but I have no idea how to update them in OS X.
- Here is my code
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); } }
解决方案Most of what you're seeing is 'normal' on Mac OS X. The C startup code does a lot of memory allocation before calling
main()
, and most of it is not freed. The suppressions are important.Creating a program like this:
int main(void) { return 0; }
and running it on my Mac OS X 10.11.4 machine (GCC 6.1.0) yields:
==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)
I get similar results compiling with
clang
from XCode. The-v
option is noisy but informative.All that memory allocation is routine, and not something it is worth worrying about.
In your output from
valgrind
, you have some possibly lost and some still reachable memory. You should explore further to find out what those are. The--leak-check=full
option will help. You may end up using--gen-suppressions
option too (valgrind --help
to explore the options available), and then--suppressions=your-suppressions-file
when rerunning.I have a file with 22 suppressions in it that I sometimes need to use. I used to have a lot more suppressions, but
valgrind
has got better at doing them automatically. Keepingvalgrind
current is generally a good idea too; rebuilding after a Mac OS X upgrade is a good idea.
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; }
Running with 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) $
Here, there's clearly one leak, from the
malloc()
at line 7 in the source code. (And this was run on Mac OS X 10.11.5 without having rebuiltvalgrind
orgcc
since the upgrade. It doesn't seem to have mattered this time around.)When you run a program on Linux, you can get a completely clean bill of health. For example, on Ubuntu 14.04 LTS, with the code as above except the
free
is uncommented out, I got the output:$ 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) $
You won't see the 'All heap blocks were free — no leaks are possible' message on Mac OS X, but you can 0 bytes lost, 0 bytes indirectly lost, 0 bytes possibly lost and 0 bytes still reachable — apart from the suppressed items — which is as good as it gets.
这篇关于GCC在OS X allocs更多的内存比预期的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!