我对C编程很陌生。
我有一个作业,其中我们应该创建一个整数的双链表,并编写一些函数来操作它们。我们被要求防止内存泄漏,但是我不太确定该怎么做。
在创建链表时,我不得不malloc
多次创建和存储节点,我敢肯定malloc
足够用于节点的空间不是一个好主意然后在同一位置释放指向它的指针。
因此,我最好的猜测是,当我将它们的内容打印到屏幕上并且不再需要它们时,我应该释放主函数中的所有节点。我试图实现一个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;
}
这里的主要功能是由教授给我们的,我们必须围绕它建立功能。
我不知道为什么这仍然会导致内存泄漏,而且,老实说,如果我真的不知道它们还会在其他地方发生。据我所知,我需要将所有内存保留到几乎最后一分钟。
请帮助,我在这里很迷路。
谢谢!
答案 0 :(得分:1)
sizeof(Node * )
更改为sizeof(Node)
。i <= arrSize
可能会溢出,因为大小通常以存储单元的数量给出。因此,您可以考虑使用i < arrSize
Node *new =
是丑陋的语法,因为new是C ++中的关键字。请不要这样做,因为那样会破坏C ++中使用的任何代码。kill()
中的临时元素。您可以改为直到head指向NULL。insert_after
相同的数组检查可能您需要调试将一个函数粘贴到另一个函数之后的整个过程,以使其正常工作。无法保证正确性,因为没有评论和全部内容,很难阅读。
答案 1 :(得分:1)
有两个问题:
malloc (sizeof(Node*))
更改为malloc (sizeof(Node))
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;
}
答案 2 :(得分:1)
查找内存泄漏的最佳方法是在运行时使用valgrind(或类似工具)。 Valgrind会识别出您遇到的任何内存泄漏或违反情况。
要在linux环境中运行valgrind,您要做的就是:
# valgrind --leak-check=full ./my_program
在您的情况下,它主要给出了以下错误:
==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)
此错误表示分配大小过小。如另一个答案中所述,这是因为您为指针分配了足够的内存,而不为结构分配了内存。