C代码函数中的分段错误

时间:2017-05-05 11:08:34

标签: c pointers segmentation-fault

struct Node {
    char gender;
    int turns_in_bathroom;
    struct Node *next;
};

struct Queue {
    struct Node *front, *back;
};

int QueueDeleteNext(Queue *myQueue, char value) {
Node *current_node, *previous_node;
previous_node = NULL;
int found = 0;
for (current_node = myQueue->front; current_node != NULL;
     previous_node = current_node, current_node = current_node->next) {
    if (current_node->gender == value) {
        if (previous_node == NULL) {
            myQueue->front = myQueue->back = NULL;
        }
        else {
            previous_node->next = current_node->next;
            if(previous_node->next == NULL){
                myQueue->back = previous_node;
            }
        }
        free(current_node);
        found = 1;
    }
}
return found;
}

我在线上遇到了分段错误

if (current_node->gender == value) {

我不能为我的生活找出原因。这里发生了什么? 更不用说尽管我的调试器中出现了错误,但代码仍会一直运行。但是,我认为可能存在一些与此相关的错误,我想确保我已经覆盖了所有基础。

3 个答案:

答案 0 :(得分:2)

for (current_node = myQueue->front; current_node != NULL;
 previous_node = current_node, current_node = current_node->next)

在for循环的每次迭代结束时,你要求current_node指向他的下一个元素。然而,下面有几行:

free(current_node);

您释放此节点。所以它指向不再分配任何东西,导致你稍后得到的分段错误。只要找到要删除的元素,就立即退出该功能:

int QueueDeleteNext(Queue *myQueue, char value) {
Node *current_node, *previous_node;
previous_node = NULL;
for (current_node = myQueue->front; current_node != NULL;
     previous_node = current_node, current_node = current_node->next) {
    if (current_node->gender == value) {
        if (previous_node == NULL) {
            myQueue->front = myQueue->back = NULL;
        }
        else {
            previous_node->next = current_node->next;
            if(previous_node->next == NULL){
                myQueue->back = previous_node;
            }
        }
        free(current_node);
        return 1;
    }
}
return 0;
}

答案 1 :(得分:2)

显然,问题已经解决,但代码仍有问题:

  • 条件next测试当前节点是否是队列的头部。在这种情况下,必须调整头部而不是前一个节点的int QueueDeleteNext(struct Queue *q, char value) { struct Node *prev = NULL; struct Node *curr = q->front; int count = 0; while (curr) { if (curr->gender == value) { struct Node *nn = curr; if (prev == NULL) { q->front = curr->next; } else { prev->next = curr->next; } if (curr == q->back) q->back = prev; curr = curr->next; free(nn); count++; } else { prev = curr; curr = curr->next; } } return count; } ,但代码会清空整个队列而不会正确删除可能的尾随节点。

  • 删除队列中的最后一个节点后,应该更新队列的后退,以便后续推送可以追加到最后。

最后,看起来有点像OP的意图是删除具有相应值的所有节点,因为执行在第一次删除后没有停止。所以让我们这样做并返回已删除节点的数量:

while

主循环现在是一个curr->next循环,用于以不同方式处理删除和跳过节点。在这两个例子中,下一个节点是prev,但是当一个节点被删除时,prev节点保持不变!此代码还保留了队列的后面。

实现此目的的另一种方法是使用指向节点指针的指针代替nd指针。这消除了区分头部和其他节点的需要。 field after that. The code updates the pointer that points to the current node via首先是队列头部的地址,以及前一个节点'下一个int QueueDeleteNext(struct Queue *q, char value) { struct Node **nd = &q->front; int count = 0; q->back = NULL; while (*nd) { if ((*nd)->gender == value) { struct Node *nn = *nd; (*nd) = (*nd)->next; free(nn); count++; } else { q->back = *nd; nd = &(*nd)->next; } } return count; } nd`的地址:

QString printPath = QSettings(classesRoot + "\\" + pdfId + "\\shell\\print\\command", QSettings::NativeFormat).value("Default").toString();

此代码可以扩展为只删除第一个节点或第一个_n_nodes。

答案 2 :(得分:-1)

在found = 1之后添加一个return语句;阻止调试器抛出错误。