使用realloc()时的SIGABRT

时间:2017-03-24 14:36:11

标签: c dynamic-memory-allocation realloc

我正在尝试为我的家庭作业制作一个C版游戏Snake。我已经为游戏实现了所有必要的机制,但是我遇到动态内存分配问题。我的蛇'存储在数组中作为正文部分列表及其位置。如果蛇吃了水果,我会尝试改变蛇的长度并在阵列上添加另一个身体片。由于我事先并不知道蛇的最终尺寸,所以我尝试使用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;
}

2 个答案:

答案 0 :(得分:0)

如果我把这两行放在一起,一个问题应该是显而易见的吗?

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

...

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

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

tableSnake[*snakeLength-1] = tempRep;

...退出该功能时会自动释放。

答案 1 :(得分:0)

效果:

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

..不会在moveSnake()函数之外传播。一个解决方法是返回&quot; tableSnake&#39;结果

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

...

tableSnake=moveSnake(&snakeLength,direction,tableSnake,extend);

如果您更清楚地命名变量,例如&#39; localSnake&#39;对于参数。尽量不要给多个var同名:)