c++ - 如何在没有 valgrind 错误的情况下释放列表中间已删除的节点?

标签 c++ linked-list valgrind free memcheck

这是一个小测试,可帮助演示和审查 valgrind 的内存检查输出。有人可以帮我弄清楚如何从列表中间删除和释放节点吗?如果我从删除节点部分注释掉 free(cur) 和 free(cur->lock),memcheck 会告诉我有内存泄漏,但如果我将它们保留在那里,那么我将在顶部进行无效读取循环。有办法解决这个难题吗?

TEST(UtilityGeneralUnittest, valgrindTests)
{
    //declare a node type
    typedef struct node{
        int size;
        int value;
        struct node *next;
        pthread_mutex_t *lock;
    }node_t;

    //make the head
    node_t *head;
    head = (node_t*)malloc(1 * sizeof(node_t));
    head->size = 0;
    head->next = NULL;
    head->lock = (pthread_mutex_t*)malloc(1 * sizeof(pthread_mutex_t));
    pthread_mutex_init(head->lock, NULL);

    //create array for storing values
    int array[10];


    //build a list with random numbers
    for (int i = 0; i < 10; i++)
    {
        node_t *newNode;
        newNode = (node_t*)malloc(1 * sizeof(node_t));
        newNode->value = rand() % 100 + 1;
        newNode->next = NULL;
        newNode->lock = (pthread_mutex_t*) malloc(1 * sizeof(pthread_mutex_t));
        pthread_mutex_init(newNode->lock, NULL);
        array[i] = newNode->value;
        if (head->next == NULL)
        {
            head->next = newNode;
            head->size++;
        }
        else
        {
            node_t *tmp = head->next;
            head->next = newNode;
            newNode->next = tmp;
            head->size++;
        }
    }
    // assert the list added nodes
    ASSERT_EQ(10, head->size);

    //sanity check; print the list
    node_t *printer = head;
    while(printer->next != NULL)
    {
        printer = printer->next;
        std::cout << "value: ";
        std::cout <<  printer->value << ", ";
    }
    std::cout << "\n";
    // the meat and potatoes: deleting with locks.
    int removeMe = array[rand() % 10];
    bool verifyDel = true;
    int checkVal = removeMe;
    node_t *prev;
    node_t *cur;

    prev = head;
    pthread_mutex_lock(prev->lock);
    while((cur = prev->next) != NULL) //******** this is the problem
    {
        pthread_mutex_lock(cur->lock);
        if(cur->value == removeMe)
        {
            prev->next = cur->next;
            pthread_mutex_unlock(cur->lock);
            pthread_mutex_unlock(prev->lock);
            cur->next = NULL;
            head->size--;
            free(cur->lock); ///******** this is the problem
            free(cur); ///****** this is the problem
        }
        pthread_mutex_unlock(prev->lock);
        prev = cur;
    }
    //pthread_mutex_unlock(prev->lock);


    //verify node has been removed
    printer = head;
    while(printer->next != NULL)
    {
        printer = printer->next;
        if(printer->value == checkVal)
        {
            verifyDel = false;
        }
        std::cout << "value: ";
        std::cout <<  printer->value << ", ";
    }
    std::cout << "\n";
    ASSERT_TRUE(verifyDel);

    //clean up: delete the list
    while((printer = head) != NULL)
    {
        head = head->next;
        free(printer->lock);
        free(printer);
        std::cout << "free!!!" << std::endl;
    }


}

最佳答案

查看您的循环(简化):

while ((cur = prev->next) != NULL) //* problem
{
    if (cur->value == removeMe)
    {
        prev->next = cur->next;
        cur->next = NULL;
        free(cur);              //* problem
    }
    prev = cur;
}

问题出在赋值 prev = cur 上,但只有在评估 if block 时才会出现问题。这已释放 cur,因此下一次循环时,cur=prev->next 引用已删除的存储。

您可以通过插入 else 来解决这个问题,以便仅在 cur 未被删除时分配 prev:

while ((cur = prev->next)) {
    if (cur->value == removeMe) {
        prev->next = cur->next;
        cur->next = NULL;
        free(cur);
    } else {
        prev = cur;
    }
}

关于c++ - 如何在没有 valgrind 错误的情况下释放列表中间已删除的节点?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37945901/

相关文章:

c++ - 如何在 Unix 中打印当前用户名和系统名?

c++ - 删除后的 CVSListBox 通知

c++ - 使用 Valgrind 工具如何检测哪个对象试图访问 0x0 地址?

c - 系统调用参数 msgsnd(msgp->mtext) 指向未初始化的字节 - 消息队列 - Valgrind

c - Valgrind 不显示行号

c++ - 为什么没有未调整大小的 Integer 类型?

c++ - 循环帮助 : string vector to 3D char vector

c++ - 链表与 C++ 和通用模板给出段错误。

c++ - 程序因为链表创建推送功能而崩溃

c - 为什么链表没有排序?