【问题标题】:Segmentation fault, while dequeuing出队时出现分段错误
【发布时间】:2020-11-15 17:09:49
【问题描述】:

我对 DS 很陌生,我正在尝试使用队列实现二叉树级顺序遍历。算法如下。

  1. 获取树的根
  2. detached_node = 根
  3. 分离节点时:
    • 打印分离节点->数据
    • 排队 detached_node->left 和 detached_node->right,如果不是 NULL
    • detached_node = dequeue()

我在 dequeue() 中遇到分段错误。这是 gdb 核心转储。

gdb main core
GNU gdb (Ubuntu 8.1-0ubuntu3.2) 8.1.0.20180409-git
This GDB was configured as "x86_64-linux-gnu".
(gdb) r
Starting program: /home/runner/DryPartialNetbsd/main 
warning: Error disabling address space randomization: Operation not permitted
[Thread debugging using libthread_db enabled]
Using host libthread_db library "/lib/x86_64-linux-gnu/libthread_db.so.1".

Program received signal SIGSEGV, Segmentation fault.
0x00000000004006d3 in dequeue ()

我不确定我在这里遗漏了什么,我正在努力理解。

下面是代码

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

struct t_node {
    int data;
    struct t_node* left;
    struct t_node* right;
};

struct t_node* create_t_node(int value) {
    struct t_node* node = (struct t_node*) malloc(sizeof(struct t_node));
    node->data = value;
    node->left = NULL;
    node->right = NULL;
    return node;
}

struct q_node {
    struct t_node* data;
    struct q_node* next;
};

struct q_node* rear = NULL;
struct q_node* front = NULL;

struct q_node* create_q_node(struct t_node* value) {
    struct q_node* node = (struct q_node*) malloc(sizeof(struct q_node));
    node->data = value;
    node->next = NULL;
    return node;
}

void create_queue(struct t_node* value) {
    struct q_node* node = create_q_node(value);
    front = node;
    rear = node;
}

void enqueue(struct t_node* value) {
    if (front == NULL && rear == NULL) {
        create_queue(value);
    } else {
        struct q_node* node = create_q_node(value);
        rear->next = node;
        front->next = node;
        rear = node;
    }
}

struct t_node* dequeue() {
    if(rear == NULL && front == NULL) 
        return NULL;
    else {
        struct q_node* node = front;
        front = front->next;
        return node->data; 
    }
}

void print_level_order(struct t_node* root) {
    if(root == NULL) {
        return;
    }
    struct t_node* detached_node = root;
    while(detached_node != NULL) {
        printf("%d ", detached_node->data);
        if(detached_node->left != NULL) {
            enqueue(detached_node->left);
        }
        if(detached_node->right != NULL) {
            enqueue(detached_node->right);
        }
        detached_node = dequeue();
    }
}

int main(void) {
    struct t_node* root = create_t_node(1);
    root->left = create_t_node(2);
    root->right = create_t_node(3);
    root->left->left = create_t_node(4);
    root->left->right = create_t_node(5);
    root->right->left = create_t_node(6);
    root->right->right = create_t_node(7);
    
    print_level_order(root);
}

【问题讨论】:

  • 尝试使用 -g3 编译并使用 valgrind/gdb 运行。 (提示:见第 55 行)
  • 顺便说一句,你为什么没有free()s?
  • 因此,输出为 1 2 3 5 7。缺少 4 和 6。好吧,这是另一个错误,与问题没有直接关系。让我再看看并接受你的回答。谢谢你的帮助:)

标签: c segmentation-fault gdb queue binary-tree


【解决方案1】:

您的问题来了,因为您在 enqueue 时更新了 rearfront,但您只在 front 时更新dequeue,所以在 dequeue 中:

if(rear == NULL && front == NULL)

如果你在 rear 非 NULL 之前至少 enqueue 一次,那么在足够的 dequeue 之后你就这样做了:

front = front->next;

front为NULL时

所以修改 dequeue 例如为

struct t_node* dequeue() {
    if(rear == NULL && front == NULL) 
        return NULL;
    else {
        struct q_node* node = front;
        front = front->next;
        if (front == NULL)
          rear = NULL;

        struct t_node* result = node->data; 
        
        free(node);
        return result;
    }
}

请注意,您还需要释放内存以避免内存泄漏

修正后:

pi@raspberrypi:/tmp $ gcc -g -Wall c.c
pi@raspberrypi:/tmp $ ./a.out
1 2 3 5 7 pi@raspberrypi:/tmp $ 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-06-03
    • 1970-01-01
    • 1970-01-01
    • 2018-10-18
    • 1970-01-01
    • 2017-02-21
    相关资源
    最近更新 更多