GCC在OS X allocs更多的内存比预期 [英] GCC on OS X allocs more memory than expected

查看:95
本文介绍了GCC在OS X allocs更多的内存比预期的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我使用的是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. Keeping valgrind 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 rebuilt valgrind or gcc 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆