尽管有堆分配(C),但堆栈溢出错误

时间:2019-02-11 20:56:12

标签: c recursion heap backtracking

我目前正在开发一个必须解决10x10字符迷宫的程序,例如以下程序:

      1   2   3   4   5   6   7   8   9  10
___________________________________________
 1|   +  []   +  []   +  []   +   +   +  []
 2|   +  []   +   +  []   +   +  []  []  []
 3|   +   +  []  []  []   +  []  []   +   +
 4|  []  []  []  []   +   +   +  []  []   +
 5|   +  []   +  []   +  []   +   +   +  []
 6|   +   +   +   +   +   +  []  []   +  []
 7|  []   +   +   +  []  []   +   +   +  []
 8|   +   +   +  []   +   +   +  []  []   +
 9|   +   +   +  []  []   +   +  []  []   +
10|   +  []   +  []   +   +  []   +   +   +

忽略数字,它们只是坐标。对于[],这只是迷宫的打印方式。实际上,无论哪里有+都意味着路径,无论哪里有[]都意味着有障碍。

我正在使用回溯算法:

void backtrack(int curX, int curY, char(*char_maze)[10], int position)
{
    if (curX < 0 || curY < 0 ||
        curX > 9 || curY > 9) {
        //out of bounds
        return;
    }
    Node tmp;
    tmp.x = curX, tmp.y = curY;
    queue(&head, &tmp);
    position++;
    if (char_maze[curX][curY] == finish) {
        //destination found TODO print path
        printf("route found");
    }
    if (char_maze[curX][curY] == path) {
        char_maze[curX][curY] = visited;
    }
    backtrack(curX, curY - 1, char_maze, position);
    backtrack(curX - 1, curY, char_maze, position);
    backtrack(curX, curY + 1, char_maze, position);
    backtrack(curX + 1, curY, char_maze, position);

    char_maze[curX][curY] = path;
    if (position) {
        del_nth(head, position);
    }
    if (!position) {
        del_first(&head);
    }
    position--;
}

正确的路由将包含一个链表,这是该列表的一个节点:

typedef struct coords {
    int     x;
    int     y;
    struct coords * next;
}Node;

backtrack(...)偶然通过一个可通过的单元格时,应该将其标记为已访问并将其添加到列表中。通过以下两个功能将其添加到列表中:

void queue(Node ** head, Node * object)
{
    Node * tmp = (Node *)malloc(sizeof(Node)); //this is the problematic line
    *tmp = *object;
    Node * last = get_last(*(head));
    if (!last) {
        (*head) = tmp;
        tmp->next = NULL;
    }
    else {
        last->next = tmp;
        tmp->next = NULL;
    }
}

Node * get_last(Node * head)
{
    while (1) {
        if (head) {
            head = head->next;
        }
        else {
            return NULL;
        }
    }
return head;
}

,并且在适当的条件下,backtrack(...)应该取消标记单元格并将其从列表中删除。删除是使用以下两个功能完成的:

void del_nth(Node * head, int index)
{
    Node * previous;
    for (int i = 0; i < index - 1; i++) {
        head = head->next;
    }
    previous = head;
    head = head->next;
    previous->next = head->next;
    free(head);
}

void del_first(Node ** head)
{
    Node * del = (*head);
    (*head) = (*head)->next;
    free(del);
}

path, visited, finish-等等,是const char-s,代表迷宫的细胞。

backtrack(...)

由用户设置的2个坐标(迷宫本身和设置为position的{​​{1}})调用。

现在,我解释了代码的工作原理,即问题所在。我已经通过Visual Studio调试器运行了这段代码,并且在此行上出现了0异常

Stack overflow (parameters: 0x00000001, 0x00492FFC).

,它是Node * tmp = (Node *) malloc(sizeof(Node)); 函数的一部分。这对我来说没有任何意义,因为queue(...)在堆上分配。我很困惑,没有解释,我不知道为什么会这样。我包含了malloc()函数中使用的所有代码,因为实际上可能存在问题。这不是调试器第一次指出错误的行。 无论如何,非常感谢您的提前帮助。

0 个答案:

没有答案