C:内存泄漏实现一个简单的链表

C: Memory leak implementing a simple linked list

我创建了一个存储整数的链表。该程序似乎 运行 正常,但 Valgrind 通知我存在内存泄漏。我不确定这怎么可能。下面提供了代码以及输出和 Valgrinds 评估。谢谢。

main.c

#include <stdio.h>
#include <stdlib.h>
#include "linked_list.h"

int main( int argc, char* argv[ ] ){
    int num = 0;
    NODE head = NULL;

    num = 7;

    head = list_insert( head, num );
    bytes_of_list( head );

    head = list_insert( head, 9 );
    bytes_of_list( head );

    head = list_insert( head, 2 );
    bytes_of_list( head );

    head = list_insert( head, 8 );
    bytes_of_list( head );

    delete_node( head, 6 );
    delete_node( head, 9 );
    bytes_of_list( head );

    print_list( head );
    printf( "\n" );

    linked_list_destroy( &head );
    bytes_of_list( head );

    return 0;
}

linked_list.c

#include <stdlib.h>
#include <stdio.h>
#include "linked_list.h"
#include "status.h"

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

/************************************************************** list insert */
NODE list_insert( NODE head, int data ){
    Node* pNode = NULL;

    printf( "\nInsert %d into list.\n", data );

    pNode = ( Node* )malloc( sizeof( Node ));
    if( !pNode ) exit( 1 );
    pNode->data = data;
    pNode->next = head;
    return pNode;
}
/******************************************************  linked_list_destroy */
void linked_list_destroy( NODE* head ){
    Node* phead = ( Node* )*head;
    Node* prevNode = NULL;

    printf( "\nDestroy List:\n");

    if( !phead ) return;
    while( phead != NULL ){
        prevNode = phead;
        phead = phead->next;
        printf( "Deleting %d\n", prevNode->data );
        prevNode->data = 0;
        prevNode->next = NULL;
        free( prevNode );
    }
    *head = NULL;
}
/***************************************************************  print_list */
void print_list( NODE head ){
    Node* pHead = ( Node* )head;

    printf( "\nPrint list:\n");

    while( pHead != NULL ){
        printf( "%d ", pHead->data );
        pHead = pHead->next;
    }
}
/***********************************************************  delete nodes */
void delete_node( NODE head, int data ){
    Node* phead = ( Node* )head;
    Node* prev = NULL;

    printf( "\nDelete %d from list:\n", data );

    if( !head ) return;
    while(( phead != NULL ) && ( phead->data != data )){
        prev = phead;
        phead = phead->next;
    }
    if( !phead ) printf( "Sorry, %d is not in the list.\n", data);
    else{
        prev->next = phead->next;
        free( phead );
    }
    return;
}
/********************************************************* bytes of list */
int bytes_of_list( NODE head ){
    Node* phead = ( Node* )head;
    int bytes_total = 0;
    while( phead != NULL ){
        bytes_total += sizeof( *phead );
        phead = phead->next;
    }
    printf( "The current size of the list is %d bytes.\n", bytes_total );
    return bytes_total;
}

linked_list.h

#ifndef LINKED_LIST_H_INCLUDED
#define LINKED_LIST_H_INCLUDED
#include "status.h"

typedef void* NODE;
NODE list_insert( NODE head, int data );
void print_list( NODE head );
void linked_list_destroy( NODE* head );
void delete_node( NODE head, int data );
Status in_list( NODE head, int data );
int bytes_of_list( NODE head );

#endif

status.h

#ifndef STATUS_H_INCLUDED
#define STATUS_H_INCLUDED
enum status {FALSE, TRUE};
typedef enum status Status;
#endif

该程序的输出如下:

将 7 插入列表。

列表的当前大小是 16 个字节。

将 9 插入列表。

列表的当前大小为 32 字节。

将 2 插入列表。

列表的当前大小为 48 字节。

将 8 插入列表。

列表的当前大小为 64 字节。

从列表中删除 6:

抱歉,6 不在列表中。

从列表中删除 9:

列表的当前大小为 48 字节。

打印列表:

8 2 7

销毁列表:

删除 8

删除 2

删除 7

列表的当前大小为 0 字节。

VALGRIND 输出:

==2758== 堆摘要:

==2758== 在退出时使用:1,198 个块中的 140,089 字节

==2758== 总堆使用量:1,968 次分配,770 次释放,分配 283,758 字节

==2758==

==2758== 泄漏摘要:

==2758== 绝对丢失:1 个块中的 10 个字节

==2758== 间接丢失:0 个块中的 0 个字节

==2758== 可能丢失:0 个块中的 0 个字节

==2758== 仍可访问:1,197 个块中的 140,079 字节

==2758== 抑制:0 个块中的 0 个字节

==2758== Re运行 with --leak-check=full 查看泄漏内存的详细信息

==2758==

==2758== 对于检测到的和抑制的错误的计数,re运行 with: -v

==2758== 错误摘要:0 个上下文中的 0 个错误(抑制:0 个中的 0 个)

这是发布代码的一个版本

  1. 全部塞进一个文件
  2. 所有建议的修复:
  3. 干净地编译
  4. 发生错误时通知用户

现在,建议的代码版本:

#ifndef STATUS_H_INCLUDED
#define STATUS_H_INCLUDED
enum status {FALSE, TRUE};
typedef enum status Status;
#endif



#ifndef LINKED_LIST_H_INCLUDED
#define LINKED_LIST_H_INCLUDED
//include "status.h"
#include <stdio.h>

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

Node* list_insert( Node *head, int data );
void print_list( Node *head );
void linked_list_destroy( Node** head );
void delete_node( Node** head, int data );
Status in_list( Node* head, int data );
void bytes_of_list( Node* head );

#endif


#include <stdio.h>
#include <stdlib.h>
//#include "linked_list.h"

int main( void )
{
    int num = 0;
    Node *head = NULL;

    num = 7;

    head = list_insert( head, num );
    bytes_of_list( head );

    head = list_insert( head, 9 );
    bytes_of_list( head );

    head = list_insert( head, 2 );
    bytes_of_list( head );

    head = list_insert( head, 8 );
    bytes_of_list( head );

    delete_node( &head, 6 );
    delete_node( &head, 9 );
    bytes_of_list( head );

    print_list( head );
    printf( "\n" );

    linked_list_destroy( &head );
    bytes_of_list( head );

    return 0;
}


//#include <stdlib.h>
//#include <stdio.h>
//#include "linked_list.h"
//#include "status.h"




/************************************************************** list insert */
Node *list_insert( Node *head, int data )
{
    printf( "\nInsert %d into list.\n", data );

    Node *pNode = malloc( sizeof( Node ));
    if( !pNode )
    {
        perror( "malloc failed" );
        exit( 1 );
    }

    pNode->data = data;
    pNode->next = head;
    return pNode;
}


/******************************************************  linked_list_destroy */
void linked_list_destroy( Node** head )
{
    Node* phead = *head;
    Node* prevNode = NULL;

    printf( "\nDestroy List:\n");


    while( phead )
    {
        prevNode = phead;
        phead = phead->next;
        printf( "Deleting %d\n", prevNode->data );
        prevNode->data = 0;
        prevNode->next = NULL;
        free( prevNode );
    }
    *head = NULL;
}


/***************************************************************  print_list */
void print_list( Node *head )
{
    Node* pHead = head;

    printf( "\nPrint list:\n");

    while( pHead )
    {
        printf( "%d ", pHead->data );
        pHead = pHead->next;
    }
}


/***********************************************************  delete nodes */
void delete_node( Node **head, int data )
{
    Node* phead = *head;
    Node* prev  = NULL;

    printf( "\nDelete %d from list:\n", data );

    //if( !head ) return;

    while(( phead ) && ( phead->data != data ))
    {
        prev = phead;
        phead = phead->next;
    }

    if( !phead ) 
    {
        printf( "Sorry, %d is not in the list.\n", data);
    }

    else
    {
        prev->next = phead->next;
        free( phead );
    }
    return;
}


/********************************************************* bytes of list */
void bytes_of_list( Node* head )
{
    Node* phead = head;
    size_t bytes_total = 0;

    while( phead )
    {
        bytes_total += sizeof( *phead );
        phead = phead->next;
    }

    printf( "The current size of the list is %lu bytes.\n", bytes_total );
    //return bytes_total;
}