双链表中的内存泄漏

问题描述 投票:0回答:3

我是C编程的新手。

我有一个赋值,我们应该在其中创建一个双向链接的整数列表,并编写一些函数来操作它们。我们被要求防止内存泄漏,但我不确定如何做到这一点。

为了在创建链接列表时创建和存储节点,我必须多次使用malloc,我很确定malloc为节点提供足够的空间然后在同一个地方释放指针并不是一个好主意。

因此,我最好的猜测是,我应该释放main函数中的所有节点,当我将其内容打印到屏幕上时不再需要它们。我试图实现一个kill函数,它将参考head作为输入作为列表中的第一个节点,并在节点上进行迭代,随时释放它们。

我甚至安装valgrind尝试看看是否有任何内存泄漏,看起来还有一些。我不知道他们来自哪里或如何解决问题。

这是整个代码:

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

 typedef struct Node{
     int data;
     struct Node *next;
     struct Node *previous;
 }Node;

 void print_dll(Node *head){
     Node *curr = head;
     while(curr != NULL){
         printf("%d\t", curr->data);
         curr = curr->next;
     }
     puts(" ");
 }

Node* create_dll_from_array(int array [], int arrSize){
     //this is a function that creates a doubly linked list 
     //with the contents of the array
     Node* current = (Node *) malloc (sizeof(Node * ));
     current->data = array[arrSize-1];
     current -> next = NULL;

     for(int i = 2; i <= arrSize; i++){
         //create a new node
         Node * temp = (Node*)malloc(sizeof(Node*));
         //I would like the dll to be in the same order as the array, I        guess it isn't strictly necessary
         temp ->data = array[arrSize-i];
         temp -> next = current;
         current-> previous = temp;
         //now make temp the current
         current = temp;
     }
     current-> previous = NULL; 
     return current;
 }

  void insert_after(Node* head, int valueToInsertAfter, int valueToInsert ){
     if(head != NULL){
         Node * current = head;

         while(current-> data != valueToInsertAfter){
         //this while loop brings 'current' to the end of the list if
         //the searched value is not there
             if(current-> next != NULL){
                 current = current->next;
             }else{
                 break;
             }
         }
         //after exiting this loop, the current pointer is pointing
         //either to the last element of the dll or to the element 
         //we need to insert after

         Node *new = (Node *) malloc (sizeof(Node *));
         new->data = valueToInsert;
         new->next = current->next;
         new->previous = current;
         if(current->next != NULL){
             (current->next)->previous = new;
         }
         current->next = new;
     }
 }

 void delete_element(Node* head, int valueToBeDeleted){
     //work in progress
 }
 void kill(Node *head){
 //this is my attempt at freeing all the nodes in the doubly linked list
     Node *current;
     while(head!=NULL){
         current = head;
         head = head->next;
         free(head);
     }
 }
 int main(){
     int array [5] = {11, 2, 7, 22, 4};
     Node *head;

     /*Question 1*/
     //creates a doubly linked list from the array below
     head = create_dll_from_array(array, 5); ///size of the array is 5

     /* Question 2 */
    // print_dll(head);

     /*Question 3*/
     // to insert 13 after the first appearance of 7
     insert_after(head, 7, 13);
     print_dll(head);
     //to insert 29 after first appearance of 21
     insert_after(head, 21, 29);
     print_dll(head);

     /*Question 6*/
     //create a function to free the whole list

     kill(head);


     return 0;

 }

这里的主要功能是由教授给我们的,我们必须围绕它建立功能。

我不知道为什么这仍然会导致内存泄漏,如果我,说实话,我真的不知道它们会发生在哪里。据我所知,我需要保留所有记忆,直到最后一分钟。

请帮忙,我在这里很丢失。

谢谢!

c pointers memory-management memory-leaks
3个回答
1
投票

有两个问题:

  1. 需要将所有malloc (sizeof(Node*))更改为malloc (sizeof(Node))
  2. 需要在kill函数中将free(header)更改为free(current)

修改后的代码如下

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

typedef struct Node {
    int data;
    struct Node *next;
    struct Node *previous;
} Node;

void print_dll(Node *head)
{
    Node *curr = head;
    while(curr != NULL) {
        printf("%d\t", curr->data);
        curr = curr->next;
    }
    puts(" ");
}

Node *create_dll_from_array(int array [], int arrSize)
{
    //this is a function that creates a doubly linked list
    //with the contents of the array
    Node *current = (Node *) malloc (sizeof(Node));
    current->data = array[arrSize - 1];
    current -> next = NULL;

    for(int i = 2; i <= arrSize; i++) {
        //create a new node
        Node *temp = (Node *)malloc(sizeof(Node));
        //I would like the dll to be in the same order as the array, I guess it isn't strictly necessary
        temp ->data = array[arrSize - i];
        temp -> next = current;
        current-> previous = temp;
        //now make temp the current
        current = temp;
    }
    current-> previous = NULL;
    return current;
}

void insert_after(Node *head, int valueToInsertAfter, int valueToInsert )
{
    if(head != NULL) {
        Node *current = head;

        while(current-> data != valueToInsertAfter) {
            //this while loop brings 'current' to the end of the list if
            //the searched value is not there
            if(current-> next != NULL) {
                current = current->next;
            } else {
                break;
            }
        }
        //after exiting this loop, the current pointer is pointing
        //either to the last element of the dll or to the element
        //we need to insert after

        Node *new = (Node *) malloc (sizeof(Node));
        new->data = valueToInsert;
        new->next = current->next;
        new->previous = current;
        if(current->next != NULL) {
            (current->next)->previous = new;
        }
        current->next = new;
    }
}

void delete_element(Node *head, int valueToBeDeleted)
{
    //work in progress
}
void kill(Node *head)
{
//this is my attempt at freeing all the nodes in the doubly linked list
    Node *current;
    while(head != NULL) {
        current = head;
        head = head->next;
        free(current);
    }
}
int main()
{
    int array [5] = {11, 2, 7, 22, 4};
    Node *head;

    /*Question 1*/
    //creates a doubly linked list from the array below
    head = create_dll_from_array(array, 5); ///size of the array is 5

    /* Question 2 */
    // print_dll(head);

    /*Question 3*/
    // to insert 13 after the first appearance of 7
    insert_after(head, 7, 13);
    print_dll(head);
    //to insert 29 after first appearance of 21
    insert_after(head, 21, 29);
    print_dll(head);

    /*Question 6*/
    //create a function to free the whole list

    kill(head);


    return 0;

}

1
投票
  1. sizeof(Node * )更改为sizeof(Node),因为malloc保留了指针指向的内存,并且需要正确数量的所需内存(不是指针而是对象本身)。
  2. i <= arrSize可能是溢出,因为大小通常是作为存储单元的数量给出的。所以你可以考虑使用i < arrSize
  3. insert_after中的第一个while循环可能指向数组后的无效内存
  4. Node *new =是一种丑陋的语法,因为new是C ++中的关键字。请永远不要这样做,因为这将破坏在C ++中使用的任何代码。
  5. 你不需要kill()中的临时元素。你可以改为直到头指向NULL。
  6. delete_element需要与insert_after相同的数组检查

可能你需要调试整个事物粘贴一个函数后,以使其正常工作。不能保证正确性,因为没有评论和所有这些都很难阅读。


1
投票

查找内存泄漏的最佳方法是在运行时使用valgrind(或类似工具)。 Valgrind将识别您遇到的任何内存泄漏或违规行为。

要在linux环境中运行valgrind,您需要做的就是:

# valgrind --leak-check=full ./my_program

在你的情况下,它给了mainy这些错误:

==28583== Invalid read of size 8
==28583==    at 0x400871: kill (aaa.c:77)
==28583==    by 0x40092D: main (aaa.c:103)
==28583==  Address 0x5204188 is 0 bytes after a block of size 8 alloc'd
==28583==    at 0x4C2DB8F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==28583==    by 0x40073A: create_dll_from_array (aaa.c:29)
==28583==    by 0x4008D9: main (aaa.c:87)

此错误表示分配大小太小。正如在另一个答案中提到的那样,这是因为你为指针分配了足够的内存,而不是为结构分配。

© www.soinside.com 2019 - 2024. All rights reserved.