c - 2个明显相同的代码!一个编译,一个抛出段错误

标签 c struct queue

我是一名初级 C 程序员,当时正在编写一个涉及队列操作的练习题,在调试时,我遇到了以下场景:

代码示例 1:

int dequeue (struct queue_node * Q) {

    struct queue_node * curr = Q->next;
    if(!Q->next)
            return -2;
    else
    {
            int s = Q->next->v_no;
            Q->next = curr->next;
            free(curr);
            return s;
    }

}

代码示例 2(以稍微修改的方式编写的相同功能):

int dequeue (struct queue_node * Q) {

    struct queue_node * curr = Q;
    if(!curr->next)
            return -2;
    else
    {
            int s = curr->next->v_no;
            Q->next = curr->next->next;
            free(curr->next);
            return s;
    }

}

预定义的数据结构如下:

struct queue_node {

    int v_no;
    struct queue_node * next;

};

void enqueue (struct queue_node * Q , int s) {

    struct queue_node * curr = Q;
    while (curr->next)
            curr = curr->next;

    curr->next = malloc(sizeof(struct queue_node));
    if(!curr->next)
            exit(10);   //No specific reason for errno 10, just wanted to exit
    curr->next->v_no = s;
    curr->next->next = NULL;

}

问题: 场景 1 中的代码允许程序成功执行并输出预期的答案,但根据我的理解,场景 2 中的代码也试图实现同样的事情,但给出了段错误。有人可以指出我是否缺乏理解或者代码本身有什么问题吗??

谢谢!

最佳答案

假设您的队列结构当前包含三个元素:

{a} -> {b} -> {c} -> NULL

当前 Q 指向 b

让我们来看看您的每个函数会做什么。

/* Example 1 (working) */
int dequeue (struct queue_node * Q) {

    struct queue_node * curr = Q->next;    // curr = {c}
    if(!Q->next)                           // c != NULL, so OK
            return -2;
    else
    {
            int s = Q->next->v_no;         // s = c.v_no
            Q->next = curr->next;          // Q->next = NULL
            free(curr);                    // free({c})
            return s;                      // return c.v_no
    }
}

因此示例 1 提供了一个指向 Q 节点的指针,使下一个节点出列并移除,返回其 v_no

/* Example 2 (segfaults) */
int dequeue (struct queue_node * Q) {

    struct queue_node * curr = Q;          // curr now points to the same element as q
    if(!curr->next)                        // {b}->next == {c}, so OK
            return -2;          
    else 
    {
            int s = curr->next->v_no;      // s = Q
            Q->next = curr->next->next;    // Q->next = NULL ({c}->next)
            free(curr->next);              // same as free (Q->next) == free(null)
            return s;
    }

}

因此在第二个示例中,您释放了一个空指针——段错误!

关于c - 2个明显相同的代码!一个编译,一个抛出段错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19523556/

相关文章:

c - C 中的显式 MOD?

c - 如何在 c 中使用 fork 和 pipe 以及 execvp 将 stdout 重定向到 stdin?

c++ - 有没有优化两个BigNums的乘法的好方法?

mongodb - 从 mongodb 中提取嵌套结构数据

go - 每个用户处理一条消息

C:无法从文件打印

c - 当进程启动时自动附加 gdb 并继续

swift - 从一个结构转换为另一个

python - 在 Python 中打印队列的内容

javascript - RSQM - 手动轮询?