【问题标题】:SIGABRT when using realloc()使用 realloc() 时的 SIGABRT
【发布时间】:2017-03-24 14:36:10
【问题描述】:

我正在尝试为我的家庭作业制作 Snake 游戏的 C 版本。我已经为游戏实现了所有必要的机制,但我在动态内存分配方面遇到了问题。我的“蛇”作为身体部位及其位置的列表存储在一个数组中。如果蛇吃了水果,我会尝试改变蛇的长度并在数组中添加另一个身体部分。因为我事先不知道蛇的最终大小,所以我尝试使用 realloc 来延长数组。下面是我的代码。注意:在导致 SIGABRT 之前,它可以工作 14 次迭代。

    #include <stdio.h>
#include <stdlib.h>
void moveSnake(int *snakeLength,int direction, int **tableSnake, int extend);
int checkItems(int **tableSnake, int **items, int itemsSize);
int selfdestruct(int **tableSnake);

/* TEST INPUT DATA: 
9
-5 4 2
-3 4 1
-2 4 1
0 4 2
1 3 3
-2 2 1
0 2 1
-7 1 1
-5 1 3
15
*/

int main() {
    int xHead = 0;
    int yHead = 0;
    int snakeLength = 1;
    int direction = 1;

    // creates the snake table


    int **tableSnake;
    tableSnake = (int **) calloc(1,1 * sizeof (int *));

    for (int i = 0; i < 1; i++) {
        tableSnake[i] = (int *) calloc(3,3 * sizeof (int));
    }

    tableSnake[0][0] = 0;
    tableSnake[0][1] = 0;
    tableSnake[0][2] = 1;


    // reads all the variables
    int noItems;
    scanf("%d", &noItems);

    int **items;
    items = (int **) malloc(noItems * sizeof (int *));

    for (int i = 0; i < noItems; i++) {
        items[i] = (int *) malloc(3 * sizeof (int));
    }

    for (int i = 0; i < noItems; i++) {
        scanf("%d", &items[i][0]);
        scanf("%d", &items[i][1]);
        scanf("%d", &items[i][2]);
    }


    int noSteps;
    scanf("%d", &noSteps);

    // start of run

    /*
     *  legend:
     *  direction: 1 - up, 2 - down, 3 - left, 4 - right
     *  typesOfItems: 5 - fruit, 6 - turn left, 7 - turn right 
     */

    int itemHead = 0;
    int extend = 0;

    for (int i = 0; i < noSteps; i++) {
        moveSnake(&snakeLength,direction,tableSnake,extend);
        extend = 0;
        itemHead = checkItems(tableSnake, items, noItems);

        if(itemHead == -1){
            if(selfdestruct(tableSnake) == 1){
                snakeLength = 0;
                break;
            };
        }
        if (itemHead == 1) {
            extend = 1;
        } else if (itemHead == 2) {
            if(direction == 1){
                direction = 3;
            }else if(direction == 2){
                direction = 4;
            }else if(direction = 3){
                direction = 2;
            }else{
                direction = 1;
            }
        } else if (itemHead == 3) {
            if(direction == 1){
                direction = 4;
            }else if(direction == 2){
                direction = 3;
            }else if(direction = 3){
                direction = 1;
            }else{
                direction = 2;
            }
        } 
    }
    printf("%d %d %d", snakeLength, tableSnake[0][0], tableSnake[0][1]);

    return (EXIT_SUCCESS);
}

void moveSnake(int *snakeLength,int direction, int **tableSnake, int extend){
    int tempX = tableSnake[0][0];
    int tempY = tableSnake[0][1];
    int tempDirection = tableSnake[0][2];

    int tempXTail = tableSnake[*snakeLength -1][0];
    int tempYTail = tableSnake[*snakeLength -1][1];
    int tempDirectionTail = tableSnake[*snakeLength -1][2];

    int tempRep[3] = {tempXTail,tempYTail,tempDirectionTail};
    if(direction == 1){
        tempY++;
    }else if(direction == 2){
        tempY--;
    }else if(direction == 3){
        tempX--;
    }else if(direction == 4){
        tempX++;
    }

    int *temp;
    temp = malloc(3 * sizeof(int));
    for(int i = 0; i < *snakeLength; i++){
        temp = tableSnake[i];
        tableSnake[i][0] = tempX;
        tableSnake[i][1] = tempY;
        tableSnake[i][2] = tempDirection;
        tempX = temp[0];
        tempY = temp[1];
        tempDirection = temp[2];
    }
    if(extend == 1){
        // this is where the error occurs
        *snakeLength = *snakeLength +1;
        tableSnake = realloc(tableSnake, *snakeLength * sizeof(int));
        tableSnake[*snakeLength-1] = tempRep;
    }

}

int checkItems(int **tableSnake, int **items, int itemsSize){
    int *item;
    item = malloc(3 * sizeof(int));
    int itemX;
    int itemY;
    int headX = tableSnake[0][0];
    int headY = tableSnake[0][1];

    for(int i = 0; i < itemsSize; i++){
        item = items[i];
        itemX = item[0];
        itemY = item[1];
        if(itemX == headX && itemY == headY){
            return item[2];
        }
    }
    return -1;
}

int selfdestruct(int **tableSnake){
    int tempX = tableSnake[0][0];
    int tempY = tableSnake[0][1];
    int lengthTable = sizeof(tableSnake)/sizeof(tableSnake[0]);

    for(int i = 1; i < lengthTable; i++){
        if(tempX == tableSnake[i][0]){
            if(tempY == tableSnake[i][1]){
                return 1;
            }
        }
    }
    return 0;
}

【问题讨论】:

  • 你有一些内存泄漏:item = malloc(3 * sizeof(int));
  • 其他问题:temp = malloc(3 * sizeof(int)); for(int i = 0; i &lt; *snakeLength; i++){ temp = tableSnake[i]; tableSnake[i][0] = tempX; tableSnake[i][1] = tempY; tableSnake[i][2] = tempDirection; tempX = temp[0]; tempY = temp[1]; tempDirection = temp[2]; } 的内容 temp 第一次全局未初始化。
  • @JohnnyMopp 这将是一个简单的解决方案,但我的作业说明指出,比赛场地的大小应该是 2.000.000x2.000.000,这太大而无法放入内存

标签: c dynamic-memory-allocation realloc


【解决方案1】:

如果我把这两行放在一起,一个问题应该很明显?

tableSnake = (int **) calloc(1,1 * sizeof (int *));

...

tableSnake = realloc(tableSnake, *snakeLength * sizeof(int));

然后你不会为新的 tableSnake 元素分配内存,而是将它指向一个局部变量...

tableSnake[*snakeLength-1] = tempRep;

...当您退出该功能时,它将自动释放。

【讨论】:

    【解决方案2】:

    效果:

    tableSnake = realloc(tableSnake, *snakeLength * sizeof(int)); 
    

    .. 不会在 moveSnake() 函数之外传播。一种解决方法是返回“tableSnake”作为结果

        int ** moveSnake(int *snakeLength,int direction, int **tableSnake, int extend){
          ...
          return tablesnake;
        );
    
    ...
    
    tableSnake=moveSnake(&snakeLength,direction,tableSnake,extend);
    

    如果您更清楚地命名变量,甚至可能不会出现此问题,例如参数的“localSnake”。尽量不要给多个 var 同名:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-07-08
      • 1970-01-01
      • 2018-12-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多