将值分配给在结构中启动的2d数组会导致无限循环

时间:2017-06-09 21:49:00

标签: c struct

typedef struct game_t {
    char gameBoard[ROWS][COLUMNS];
} Game;


Game* Create(){
    Game *thegame = (Game *)malloc(sizeof(Game*));
    if (thegame==NULL || historySize<=0){
        return NULL;
    }
    int row=0, col=0;
    for (row = 0; row<ROWS; row++){
        for (col = 0; col<COLUMNS; col++){
            thegame->gameBoard[row][col] = EMPTY_ENTRY;
        }
    }
    return thegame;
}

我试图运行上面的代码并为结构中初始化的2d数组赋值(大写字母都是#define值)。出于某种原因,我在eclipse中不断进入无限循环。我构建项目时没有引发任何标志,就在我运行它时。 谁能请我解释一下我做错了什么?

谢谢!

2 个答案:

答案 0 :(得分:1)

声明Game *thegame = (Game *)malloc(sizeof(Game*))肯定是错误的;与thegame->gameBoard[row][col] = EMPTY_ENTRY一起,当您访问未分配的内存时,它会引入未定义的行为。所以你应该写Game *thegame = malloc(sizeof(Game))代替。请注意,在C中,最好malloc的结果转换为有争议的here

无论如何,如果将EMPTY_ENTRY定义为值0,您还可以使用calloc,它会使用0初始化内存。因此,您可以省略for - 循环(参见cppreference/calloc):

  

void* calloc( size_t num, size_t size );为数组分配内存   大小为num的{​​{1}}个对象,并初始化已分配的所有字节   存储到零。

答案 1 :(得分:1)

该功能有两个问题。

首先是这句话

Game *thegame = (Game *)malloc(sizeof(Game*));

分配大小等于指针Game*大小的内存,而不是分配大小等于结构Gamestruct game_t大小相同的内存。

你必须写

Game *thegame = (Game *)malloc(sizeof(Game));

Game *thegame = (Game *)malloc(sizeof(struct game_t));

第二个问题是,如果变量historySize小于或等于0,则可能存在内存泄漏。

考虑到最好将函数参数指定为void

函数定义可以采用以下方式

Game * Create( void )
{
    Game *thegame = NULL;

    if ( historySize > 0 && ( thegame = malloc( sizeof( Game ) ) ) != NULL )
    { 
        for ( int row = 0; row < ROWS; row++ )
        {
            for ( int col = 0; col < COLUMNS; col++ )
            {
                thegame->gameBoard[row][col] = EMPTY_ENTRY;
            }
        }
    }

    return thegame;
}

当函数处理全局变量时也不是一个好主意。您可以将变量historySize作为参数传递给函数。

在这种情况下,函数看起来像(我想变量historySize的类型是int

Game * Create( int  historySize )
{
    Game *thegame = NULL;

    if ( historySize > 0 && ( thegame = malloc( sizeof( Game ) ) ) != NULL )
    { 
        for ( int row = 0; row < ROWS; row++ )
        {
            for ( int col = 0; col < COLUMNS; col++ )
            {
                thegame->gameBoard[row][col] = EMPTY_ENTRY;
            }
        }
    }

    return thegame;
}

在这种情况下,可以像

一样调用该函数
Create( historySize );

有可能将循环替换为标准函数memset的调用。

例如

#include <string.h>

//...

Game * Create( int  historySize )
{
    Game *thegame = NULL;

    if ( historySize > 0 && ( thegame = malloc( sizeof( Game ) ) ) != NULL )
    {
        memset( thegame->gameBoard, EMPTY_ENTRY, ROWS * COLUMNS ); 
    }

    return thegame;
}