c - 在 c 中为队列推送中的临时分配内存时出错,来自 valgrind 的写入大小为 8 无效

标签 c pointers queue push valgrind

这是我的推送功能

void push(struct Map *map, struct Location location){
    struct Node *temp = map->front;
    temp->loc = location; //this line causes the error
    temp->next = NULL;

    if(map->rear == NULL) { // if queue empty
        map->front = temp; // First NODE 
        map->rear = map->front;
    }else{// if there is stuff in the queue
        map->rear->next = temp; 
        map->rear = temp;
        // Insert End 
    }
    free(temp);
}

我收到此错误

==2301== Invalid write of size 8
==2301==    at 0x401148: push (3146.c:239)
==2301==    by 0x400DE7: findEntrance (3146.c:164)
==2301==    by 0x400820: main (3146.c:55)
==2301==  Address 0x0 is not stack'd, malloc'd or (recently) free'd
==2301== 

我正在对排列成迷宫的字符网格进行广度优先搜索。我一直无法避免内存泄漏,所以我终于发现使用 malloc 有帮助,但我不明白为什么我不能在没有段错误的情况下执行此数据分配

另一种方法是不释放它并导致内存泄漏,我认为这不是一个可接受的解决方案。我的逻辑哪里错了?

下面是整个程序

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

struct Location;
struct Map;
struct Node;

//function names seem to self describe
void pathFinder(struct Map*);
void findEntrance(struct Map*);
void readInMap(struct Map*);
void printMap(struct Map*);//to screen
/* Q funcs */
void pop(struct Map*);
void push(struct Map*, struct Location);


struct Location {// simple location type 
    int x;
    int y;
};
struct Node {//standard linked list node
    struct Location loc;
    struct Node *next;
};
struct Map { //variable size encompassing array, and dimension variables
    char arr[100][100];
    int xLength;//dimensions
    int yLength;
    int complete;
    struct Node *rear;//Q pointers
    struct Node *front;
    struct Node *currLoc; //temp for BFS
    struct Location entrance;
};


int main(){
    struct Map map;//the one map to rule them all
    map.xLength = 0;//map dimensions
    map.yLength = 0;
    map.front = NULL; // queue pointers init
    map.rear = NULL;
    map.currLoc = NULL;
    map.entrance.x = 0;
    map.entrance.y = 0;
    map.complete = 0;

    readInMap(&map);
    findEntrance(&map);//start off by finding where to start
    pathFinder(&map); // problem solver method 
    printMap(&map);

    free(map.front);
    free(map.rear);
    free(map.currLoc);
    return 0;

}

void pathFinder(struct Map *map){
    int x;//should be the entrance already pushed from findEntrance
    int y;
    int done = 0;
    struct Location temp;
    temp.x = 0;// temp for pushing locations that are adjacent 0's
    temp.y = 0;

    while(map->front != NULL){
        map->currLoc = map->front;//currLoc is just a copy so that we can pop the map location of currLoc from Q
        pop(map);// pop so it cant be used twice in this loop
        x = map->currLoc->loc.x;
        y = map->currLoc->loc.y;
        temp.x = 0;
        temp.y = 0;

        if(map->arr[y][x] == '0'){//protection of 1 values from replacement
            map->arr[y][x] = 'X';//replace the array position loc w x
        }

        if(map->arr[y][x] == '0'){//protection of 1 values from replacement
            map->arr[y][x] = 'X';//replace the array position loc w x
            printf("test\n");
        }
            /* find adjacent 0's */
        if((y < map->xLength)&&(map->arr[y+1][x] == '0')){
            temp.x = x;
            temp.y = y+1;
            push(map, temp);
        }
        if((x < map->xLength)&&(map->arr[y][x+1] == '0')){
            temp.x = x+1;
            temp.y = y;
            push(map, temp);
        }
        if((y > 0)&&(map->arr[y-1][x] == '0')){
            temp.x = x;
            temp.y = y-1;
            push(map, temp);
        }
        if((x > 0)&&(map->arr[y][x-1] == '0')){
            temp.x = x-1;
            temp.y = y;
            push(map, temp);
        }
        if((x == 0)||(x == map->xLength)||(y == 0)||(y == map->yLength)){  //then its not on the edge
            if((x != map->entrance.x)&&(y != map->entrance.y)){
               map->front = NULL;
               map->complete++;
            }
        }
    } 
}

void findEntrance(struct Map *map){
    struct Location entrance;
    int done = 0;
    int y=0;//index of current row depth
    int x=0;//index of current column depth
    if (done == 0){
        for (x=0;x<=map->xLength;x++){ // top row
            if (map->arr[y][x] == '0') {
                entrance.x = x;
                entrance.y = y;
                done = 1;
            }
        }
    }
    if (done == 0){
        for(y=0;y<=map->yLength;y++){//down the right side
            if (map->arr[y][map->xLength] == '0') {
                entrance.x = x;
                entrance.y = y;
                done = 1;
            }
        }
    }
    if (done == 0){
        for(x;x>=0;x--){//bottom row RtoL
            if (map->arr[map->yLength][x] == '0') {
                entrance.x = x;
                entrance.y = y;
                done = 1;
            }
        }
    }
    if (done == 0){
        for(y;y>=0;y--){//up the left side
            if (map->arr[y][0] == '0') {
                entrance.x = x;
                entrance.y = y;
                done = 1;
            }
        }
    }

    map->entrance = entrance;
    push(map, map->entrance);
}

void readInMap(struct Map *map){
    FILE *fptr;
    char c;
    char file_name[20];
    int i,j;
    int rows;
    int cols;
    int x,y;
    printf("Size\n");
    printf("Rows:");
    scanf("%i", &rows);
    printf("Columns:");
    scanf("%i", &cols);

    map->xLength = cols-1; //[y][xLength]
    map->yLength = rows-1; //[yLength][x]
    for (x=0;x<100;x++){
        for (y=0;y<100;y++){
            map->arr[x][y] = '1';//whole array is 1
        }
    }

    printf("Type in the name of the file containing the Field\n");
    scanf("%s",file_name);
    fptr=fopen(file_name, "r");
    for (i = 0; i <= map->xLength; i++){
        for (j = 0; j <= map->yLength; j++){
            c=fgetc(fptr); //handles new line character and spaces
            while ( !((c == '1') || (c =='0')) ) {
                c=fgetc(fptr);
            }
            map->arr[i][j] = c;
        }
    }
    printf("\n");
    fclose(fptr);
}

void printMap(struct Map *map){
    int y;//index of current row depth
    int x;//index of current column depth
    for (x=0;x<=map->xLength;x++){
        for (y=0;y<=map->yLength;y++){//current pos (x,y)
            printf("%c", map->arr[x][y]);
        }
        printf("\n");
    }
    if(map->complete != 0){
        printf("\n An exit to the maze was found that is not the entrance\n");
    }else{
        printf("\n No exit was found  \n");
    }
}


void pop(struct Map *map){
    if (map->front != NULL){//if not empty
        if (map->front == map->rear){
            map->rear = NULL;//if the line length is 1, empty it
            map->front = NULL;
        }else{
            map->front = map->front->next;//next in line
        }
    }else{
        map->rear = NULL;//empty out the queue
        map->front = NULL;
    }
}

void push(struct Map *map, struct Location location){
    struct Node *temp = (struct Node*)malloc(sizeof(struct Node));
    temp->loc = location;
    temp->next = NULL;

    if(map->rear == NULL) { // if queue empty
        map->front = temp; // First NODE 
        map->rear = map->front;
    }else{// if there is stuff in the queue
        map->rear->next = temp; 
        map->rear = temp;
        // Insert End 
    }
    free(temp);
}

最佳答案

Map为空时,frontrear都为NULL。因此 temp->loc 取消引用 NULL 指针。

您需要malloc新节点并将其添加到列表中。此外,您不想在此处free,因为这会释放您刚刚添加到列表中的内存。

void push(struct Map *map, struct Location location){
    struct Node *temp = malloc(sizeof(struct Node));
    temp->loc = location;
    temp->next = NULL;

    if(map->rear == NULL) { // if queue empty
        map->front = temp; // First NODE 
        map->rear = map->front;
    }else{// if there is stuff in the queue
        map->rear->next = temp; 
        map->rear = temp;
        // Insert End 
    }
}

pop 中是您要释放内存的位置:

void pop(struct Map *map){
    struct Node *temp = map->front;

    if (map->front != NULL){//if not empty
        if (map->front == map->rear){
            map->rear = NULL;//if the line length is 1, empty it
            map->front = NULL;
        }else{
            map->front = map->front->next;//next in line
        }
        free(temp);
    }else{
        map->rear = NULL;//empty out the queue
        map->front = NULL;
    }
}

关于c - 在 c 中为队列推送中的临时分配内存时出错,来自 valgrind 的写入大小为 8 无效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/35323251/

相关文章:

c - 术语帽 : Get cursor position

c - 运行时检查失败 #2 - 变量 'input' 周围的堆栈已损坏

c - "Ex"在 Windows API 函数名中代表什么?

c - 为什么 GCC 只能在 int 大小是编译时常量时进行循环交换优化?

c# - 将 StringBuilder 传递给需要 char 指针的 DLL 函数

javascript - 在 Node.js 上为用户排队的一种方法

c - 引用/取消引用身份

c - 如何声明函数一次传递一个参数 argv[i]?在C中

c++ - 如何在 std::queue 中存储 char 缓冲区

node.js - 使用 Node js 从 Oracle AQ 中提取消息