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 个)
这是发布代码的一个版本
- 全部塞进一个文件
- 所有建议的修复:
- 干净地编译
- 发生错误时通知用户
现在,建议的代码版本:
#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;
}
我创建了一个存储整数的链表。该程序似乎 运行 正常,但 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 个)
这是发布代码的一个版本
- 全部塞进一个文件
- 所有建议的修复:
- 干净地编译
- 发生错误时通知用户
现在,建议的代码版本:
#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;
}