You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Valgrind检测到未初始化值问题,求助排查C++队列代码错误

链表队列的未初始化值与内存问题排查

实现基于链表的队列时,使用Valgrind检测到「Conditional jump or move depends on uninitialised value(s)」错误,尝试调试未找到问题,相关代码、测试用例及Valgrind输出如下:

问题代码

#include <fstream>
#include <iostream>
#include <string>
using namespace std;

struct Node{
    string item;
    Node* next;
    Node* prev;
};
struct Queue{
    int size;
    Node* head = NULL;
    Node* tail = NULL;

};
//Makes queue
Queue* createQueue(){
    Queue* n = new Queue;
    n->head = NULL;
    n->tail = NULL;
    n->size = 0;
    return n;
}
//checks if empty
bool isEmpty(Queue* List){
    if( List->size == 0){
        return true;
    }else{
        return false;
    }
}
// add item to queue
bool enqueue(Queue* List, string added){
    Node* newy= new Node;
    if(List->tail == NULL){
        List->head = List->tail = newy;
        return true;
    }
    List->tail->next = newy;
    List->tail = newy;
    List->size++;
    return true;
}
//remove item from queue
string dequeue(Queue* List){
    Node* tempo = List->head;
    if(List->head == NULL){
        return "ERROR";
    }
    else if (tempo->next !=NULL){
        tempo = tempo->next;
        return List->head->item;
        free(List->head);
        List->head = tempo;
    }else{
        return List->head->item;
        free(List->head);
        List->head= NULL;
        List->tail = NULL;
    }
}

// display the queue
void print(Queue* List){
    Node* yuuur = List->head;

    while(yuuur != NULL){
        cout<<(yuuur->item)<<endl;
        yuuur = yuuur->next;
    }
}
// destroy queue
void destroyQueue(Queue* List){
    while(List->head !=NULL){
        Node *tempo = List->head;
        List->head= List->head->next;
        delete tempo;
    }
    List->tail = NULL;
    List->head = NULL;
    delete List;

}

测试代码

//test code
int main(){
    Queue* q = createQueue();
    cout << boolalpha << isEmpty(q) << endl;
    cout << dequeue(q) << endl;
    enqueue(q, "Jos");
    enqueue(q ,"An");
    enqueue(q, "Peter");
    print(q);             //Jos, An en Peter worden op drie regels geprint
    string first = dequeue(q);
    cout << first << endl;  //Jos wordt geprint
    print(q);           //An en Peter worden geprint
    destroyQueue(q);
    return 0;
}

Valgrind错误输出

==77== Memcheck, a memory error detector
==77== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==77== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
==77== Command: student/labo13
==77==
==77== Conditional jump or move depends on uninitialised value(s)
==77==    at 0x400DDA: print(Queue*) (in /task/student/labo13)
==77==    by 0x401002: main (in /task/student/labo13)
==77==
==77== Conditional jump or move depends on uninitialised value(s)
==77==    at 0x400DDA: print(Queue*) (in /task/student/labo13)
==77==    by 0x40103F: main (in /task/student/labo13)
==77==
==77== Conditional jump or move depends on uninitialised value(s)
==77==    at 0x400DDA: print(Queue*) (in /task/student/labo13)
==77==    by 0x401097: main (in /task/student/labo13)
==77==
==77== Conditional jump or move depends on uninitialised value(s)
==77==    at 0x400E23: destroyQueue(Queue*) (in /task/student/labo13)
==77==    by 0x4010A3: main (in /task/student/labo13)
==77==
==77==
==77== HEAP SUMMARY:
==77==     in use at exit: 0 bytes in 0 blocks
==77==   total heap usage: 10 allocs, 10 frees, 263 bytes allocated
==77==
==77== All heap blocks were freed -- no leaks are possible
==77==
==77== For counts of detected and suppressed errors, rerun with: -v
==77== Use --track-origins=yes to see where uninitialised values come from
==77== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 0 from 0)

问题根源及修复方案

1. Node节点未初始化

创建Node对象时,next和prev指针未赋值,导致后续遍历(如print函数中访问yuuur->next)时读取未初始化的垃圾值,触发Valgrind错误。
修复:创建节点时初始化所有成员:

Node* newy = new Node{added, nullptr, nullptr};

2. enqueue函数size更新遗漏

当队列是空的(tail == NULL),添加第一个节点后未更新size,导致size值始终比实际元素数少1。
修复:在空队列添加节点后同步更新size:

if(List->tail == NULL){
    List->head = List->tail = newy;
    List->size++; // 新增这行
    return true;
}

3. dequeue函数逻辑错误

return语句在内存释放代码之前,导致free/delete永远不会执行,且C++中new分配的内存必须用delete释放,不能混用free。
修复:先保存要返回的元素,再释放内存,最后返回:

string dequeue(Queue* List){
    if(List->head == NULL){
        return "ERROR";
    }
    Node* tempo = List->head;
    string item = tempo->item; // 先保存元素
    if (tempo->next != nullptr){
        List->head = tempo->next;
    }else{
        List->head = nullptr;
        List->tail = nullptr;
    }
    delete tempo; // 用delete释放
    List->size--; // 更新size
    return item;
}

4. destroyQueue的指针访问风险

未初始化的next指针会导致循环中读取垃圾值,修复节点初始化后此问题自动解决。


修复后的完整代码

#include <fstream>
#include <iostream>
#include <string>
using namespace std;

struct Node{
    string item;
    Node* next;
    Node* prev;
};
struct Queue{
    int size;
    Node* head = nullptr;
    Node* tail = nullptr;
};

Queue* createQueue(){
    Queue* n = new Queue;
    n->head = nullptr;
    n->tail = nullptr;
    n->size = 0;
    return n;
}

bool isEmpty(Queue* List){
    return List->size == 0;
}

bool enqueue(Queue* List, string added){
    Node* newy = new Node{added, nullptr, nullptr};
    if(List->tail == nullptr){
        List->head = List->tail = newy;
        List->size++;
        return true;
    }
    List->tail->next = newy;
    newy->prev = List->tail; // 双向链表维护prev指针
    List->tail = newy;
    List->size++;
    return true;
}

string dequeue(Queue* List){
    if(List->head == nullptr){
        return "ERROR";
    }
    Node* tempo = List->head;
    string item = tempo->item;
    if (tempo->next != nullptr){
        List->head = tempo->next;
        List->head->prev = nullptr;
    }else{
        List->head = nullptr;
        List->tail = nullptr;
    }
    delete tempo;
    List->size--;
    return item;
}

void print(Queue* List){
    Node* yuuur = List->head;
    while(yuuur != nullptr){
        cout << yuuur->item << endl;
        yuuur = yuuur->next;
    }
}

void destroyQueue(Queue* List){
    while(List->head != nullptr){
        Node *tempo = List->head;
        List->head = List->head->next;
        delete tempo;
    }
    delete List;
}

//test code
int main(){
    Queue* q = createQueue();
    cout << boolalpha << isEmpty(q) << endl;
    cout << dequeue(q) << endl;
    enqueue(q, "Jos");
    enqueue(q ,"An");
    enqueue(q, "Peter");
    print(q);
    string first = dequeue(q);
    cout << first << endl;
    print(q);
    destroyQueue(q);
    return 0;
}

内容的提问来源于stack exchange,提问作者FieldyScop

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.09 17:30:46