C程序中的内存错误,名称消失了吗?

时间:2011-09-22 06:52:50

标签: c

我试图在c中制作一个简单的游戏http://pastebin.com/BxEBB7Z6。目标是通过获取随机数字来尽可能接近21来击败计算机。

每轮比赛都会显示球员的名字和总和,但由于某些原因,它只能在第一次使用?像这样:

球员约翰总和0。 玩家总和9。 玩家总和为11。

等等。

为什么玩家的名字会显示一次,但之后没有任何其他打印?我不在某处重新分配: - )

我使用函数void PrintPlayerSum(struct Player *p)将其打印出来,它第一次运行,但仅限于此。

#include <stdio.h>
#include <stdlib.h>

#include <time.h>

struct Player
{
    char name[256];
    int sum;
};

void PrintPlayerSum(struct Player *p)
{
     printf("Player %s has sum %d\n", p->name, p->sum);
}

void wait ( int seconds )
{
    clock_t endwait;
    endwait = clock () + seconds * CLOCKS_PER_SEC ;
    while (clock() < endwait) {}
}

int main()
{
    struct Player *player = malloc(sizeof(*player));
    strcpy( player->name, "John");
    player->sum = 0;

    while(1)
    {
        PrintPlayerSum(player);

        printf("Do you want another number? (y/n, q for quit) ");
        char ch;

        scanf("%s", &ch);

        if( ch == 'q' )
            break;

        if( ch == 'y' )
        {
            srand(time(NULL));

            int rnd = rand() % 13 + 1;
            player->sum += rnd;

            printf("Player got %d\n", rnd);
        }

        if( ch == 'n' || player->sum > 21)
        {
            if( player->sum > 21 )
            {
                printf("\n*** You lost the game, please try again... ***");
            }
            else
            {
                printf("\nCPU's turn\n");

                int cpusum = 0;

                while( 1 )
                {
                       if( cpusum > 21 )
                       {
                           printf("\n*** CPU lost the game with the score %d, you win! ***", cpusum);
                           break;
                       }

                       if( cpusum > player->sum )
                       {
                           printf("\n*** CPU won the game with the score %d, please try again ***", cpusum);
                           break;
                       }

                       wait(1);
                       srand(time(NULL));
                       int rnd = rand() % 13 + 1;
                       cpusum += rnd;

                       printf("CPU got %d, sum is %d\n", rnd, cpusum);
                }
            }

            break;
        }

        printf("\n\n");
    }

    /* Cleanup ******************/
    free(player);
    /****************************/

    printf("\n\n\n");
    system("PAUSE");
    return 0;
}

5 个答案:

答案 0 :(得分:5)

我怀疑问题是你使用scanf。你说你想要读取一个以零结尾的字符串,但是你将它填充到一个字符串中。变量在堆栈上的布局方式导致终止零字节最终成为player-&gt; name中的第一个char。

尝试输入“缓冲区溢出”而不是“y”,你应该得到“播放器uffer溢出去......”。

如果您想坚持使用scanf,您需要确保传递正确的字符串并设置目标缓冲区大小的限制。要阅读一个字符,请尝试fgetc。

修改 上面当然不太正确......它是一个缓冲区溢出,但它是被覆盖的播放器结构的指针。幸运的是巧合,你得到一个指向零字节的有效地址。通过输入更多内容,您很可能会遇到崩溃。

答案 1 :(得分:3)

您的scanf调用可能是问题:

scanf("%s", &ch);

你似乎想要一个角色,但是你正在读一个字符串。它会把第一个字符放在ch中,但是继续从那里开始并覆盖堆栈中的下一个字符。

如果单个字符符合您的要求,您应该只使用fgetc(stdin)或其他读取单个字符的函数。

答案 2 :(得分:2)

不应该是

struct Player *player = malloc(sizeof(struct Player));

答案 3 :(得分:1)

像这样奇怪的事情通常是由写入未分配的内存引起的。 (通常写在数组末尾之外。)

我没有看你的代码,而是搜索那样的东西。然后在valgrind下运行您的程序。

答案 4 :(得分:0)

乍一看,我可以看到你做了:

    scanf("%s", &ch);

将使用ch的地址输入字符串,从而导致缓冲区溢出。你需要做

  ch = getchar ();
  scanf ("%c", &ch);