This is the struct:
typedef struct listeEle {
int pos;
struct listeEle *next;
} ListEle;
this is where I create the list:
ListEle *mokli(int n){
if(n<=0)
{
fprintf(stderr, "Falscher Parameter für mokli... Programm beendet.");
exit(0);
}
else
{
ListEle *lst;
lst = malloc(sizeof(ListEle));
lst->next = NULL;
lst->pos = 1;
int i;
ListEle *new;
ListEle *ptr;
ptr = lst;
for(i=1; i<n; i++)
{
new = NULL;
new = malloc(sizeof(ListEle));
new->next = NULL;
new->pos = i+1;
ptr->next = new;
ptr = ptr->next;
}
return lst;
}
}
and this is where I try to free it
void unmokli(ListEle *lst)
{
if(lst->next == NULL)
{
free(lst);
lst = NULL;
printList(lst);
printf("1 > Liste vollständig gelöscht.\n");
}
else
{
ListEle *head;
head = lst;
int del = 0;
while(head)
{
ListEle *temp = head;
head = head->next;
free(temp);
del+=1;
}
free(lst);
lst = NULL;
printf("2 > Liste deleted (%d).\n", del);
}
}
This is how I print it
void printList(ListEle *anfang){
if(anfang == NULL)
{
printf("List not av...\n");
}
else
{
ListEle *ptr;
ptr = anfang;
int i = 1;
while(ptr)
{
printf("Element %i -> ListeEle pos=%i\n", i++, ptr->pos);
ptr = ptr->next;
}
}
}
The problem is in the main method. The list I create here won't be freed, although I pass it correctly to the freeing function.
int main(void){
ListEle *liste;
liste = mokli(6);
printList(liste);
unmokli(liste);
printList(liste);
return 0;
}
After unmokli it should be freed completely, but the list inside the main function is still allocated. How can I completely free the list?
When you do
lst = NULL;
in the function unmokli you are only making the local copy lst NULL. Remember that arguments are passed by value, i.e. they are copied. You need to pass lst by reference, which can be done by passing a pointer (to the pointer):
void unmokli(ListEle **lst)
{
...
*lst = NULL;
...
}
You then call this by using the address-of operator:
unmokli(&liste);
Either pass reference of liste to unmokli() or take return parameter from it as you have done in mokli().
In your case, its getting freed, but variable liste in main() is not set to NULL and still references old memory. This is may cause you crash.
Update your code as
void unmokli(ListEle **lst_ref)
{
ListEle *lst = *lst_ref;
...
//your code freeing list
//set to null after freeing
*lst_ref = NULL;
}
From main() call it as
unmokli(&liste);
It's freed, but data still remains after calling free, so you just accessing deleted data by printing list after delete. (which you mustn't do actually)
Also, if you want to set 'liste' pointer to NULL inside free-function, you should pass pointer to a pointer. The following code in unmokli is useless:
free(lst); // Already freed in a loop before
lst = NULL; // Takes effect only inside this function
Typically, I would free (& NULL assign) the linked list as below:
void unmokli(ListEle **lst)
{
ListEle* nxt;
if(lst==NULL) return;
// printList(*lst); // not required by the free-list logic as such...
while(*lst)
{
nxt=(*lst)->next;
// printList(*lst); // not required by the free-list logic as such... You can test free code with this.
free(*lst);
*lst=nxt;
}
}
//usage
unmokli(&list_head);
Related
I am required to have a list of structs of sentence nodes that point to a struct of word nodes. I am trying to print the user's input.
I have a program that runs properly when I manually give it the input (see test section of the code). It does not, however, work when I use my input1() function.
I've tried debugging it, but I can't seem to find the problem.
I removed all printf lines that I used to debug. I also removed all the irrelevant code.
I am looking to know how to fix it and what is wrong so I can run it with no problems.
What I learned from debugging it is that (only when using input1() and not in the test) the head is overwritten every time and all the nodes as well.
I also tried using a double pointer instead of returning para but that didn't help.
any help will be appreciated,
thanks in advance
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
typedef struct word
{
char * ch;//poiter to char
}
W;
typedef struct sentence
{
W * currentWord;//pointer to a word
int lineNumber;// holds the line number
int numbersOfWords;//holds the number of words
struct sentence* link;
}
sent;
typedef struct list
{
sent* head;
int count;
}
LISTS;
LISTS* createList()
{
LISTS* list;
list= (LISTS*) malloc (sizeof (LISTS));
if (list)
{
list-> head = NULL;
list-> count = 0;
}
return list;
} // createList
void printList(LISTS* list)
{
sent *temp = list -> head;
//iterate the entire linked list and print the data
while(temp != NULL)
{
printf("%s\n", temp->currentWord->ch);
temp = temp->link;
}
// printf("NULL\n");
}
void insertSentList (LISTS* list, W* itemPtr)
{
sent* newPtr; //new node
if (!(newPtr = (sent * ) malloc(sizeof(sent)))){
printf(" Memory can not be allocated.");
return;
}
newPtr->currentWord = itemPtr;
newPtr->link = NULL;
if(list->head == NULL)
{
list->head = newPtr;
}else{
sent* current = list->head;
while(current->link != NULL){
current = current->link;
}
current -> link = newPtr;
}
(list->count)++;
return;
} // insertList
LISTS * input1(LISTS *para)
{
char * line;
line = (char * ) malloc(1000 * sizeof(char));
line[0] = '\0';
while (line[0] != '\n')
{
W word;
word.ch = (char * ) malloc(100);
printf(" Please input a line : ");
fgets(line, 1000, stdin);
if(line[0] != '\n'){
strcpy(word.ch, line);
insertSentList(para,&word);
}
}
free(line);
return para;
}
int main()
{
///////////////////test////////////////
LISTS* list = createList();
W word;
word.ch= "word0 ";
W word1;
word1.ch= "word1 ";
W word2;
word2.ch= "word2";
insertSentList(list,&word);
insertSentList(list,&word1);
insertSentList(list,&word2);
insertSentList(list,&word);
insertSentList(list,&word1);
insertSentList(list,&word2);
printList(list);
///////////////////test////////////////
LISTS *para = createList();
para= input1(para);
printList(para);
return 0;
}
Main problem with the posted code is that "ownership" of the sent and W objects in a list is not well defined. For example word.ch= "word0 "; in main sets the ch pointer pointing to a string literal (which it does not own), but word.ch = malloc(100); in input1 points it to dynamically allocated memory (which it should own, and remember to free later). Because of this, memory allocations cannot be tracked reliably and, even in the cases where things appear to "work", there are multiple memory leaks. It also breaks when the inserted objects are local variables that do not live for the entire lifetime of the list object.
The simplest (if not necessarily the best or most efficient) solution would be to dynamically allocate all objects that go into the list, make the list own them all, and add a function to cleanup once done. To that end insertSentList could be modified as follows.
void insertSentList (LISTS* list, W* itemPtr)
{
sent* newPtr; //new node
if (!(newPtr = malloc(sizeof(sent)))){
printf(" Memory can not be allocated.\n");
return;
}
W *newItem = malloc(sizeof(W)); // <-- make a deep copy of the `itemPtr` argument
newItem->ch = strdup(itemPtr->ch); // including a copy of the string itself
newPtr->currentWord = newItem; // <-- save the copy in the list, not the argument
newPtr->link = NULL;
if(list->head == NULL)
{
list->head = newPtr;
}else{
sent* current = list->head;
while(current->link != NULL){
current = current->link;
}
current->link = newPtr;
}
list->count++;
} // insertList
For proper cleanup and to avoid memory leaks, the following freeList should be called for each list pointer returned by createList and filled by insertSentList.
void freeList(LISTS *list)
{
sent *temp = list->head;
while(temp != NULL)
{
sent *next = temp->link;
free(temp->currentWord->ch);
free(temp->currentWord);
free(temp);
temp = next;
}
free(list);
}
Kindly read the whole post since it includes small details which are highly important.
As known by C we should take care of incidents where malloc fails, for that case I created a function called destroyList() whose job is to take a pointer to Node and destroy it one by one.
But my function isn't being called correctly...
I tried to call it with ptr, merged_out and *merged_out (The last one was a suggestion from a member of the community) but nothing seems to work.
Why is that? the function sometimes receives NULL, Empty Lists or some random values.
Can someone please help me fix this issue and let me understand of what is going on?
typedef struct node_t {
int x;
struct node_t *next;
} *Node;
void destroyList(Node ptr) {
while (ptr) {
Node toDelete = ptr;
ptr = ptr->next;
free(toDelete);
}
}
Main Function:
ErrorCode mergeSortedLists(Node list1, Node list2, Node *merged_out) {
if (!list1 || !list2) {
return EMPTY_LIST;
}
if (!isListSorted(list1) || !isListSorted(list2)) {
return UNSORTED_LIST;
}
if (!merged_out) {
return NULL_ARGUMENT;
}
Node ptr = NULL;
int total_len = getListLength(list1) + getListLength(list2);
for (int i = 0; i < total_len; i++) {
int min = getMin(&list1, &list2);
ptr = malloc(sizeof(*ptr));
*merged_out = ptr;
if (!ptr) {
destroyList(*merged_out);
*merged_out = NULL;
return MEMORY_ERROR;
}
ptr->x = min;
ptr->next = NULL;
merged_out = &ptr->next;
}
return SUCCESS;
}
This is how the function should be called:
Node merged_actual = NULL;
ErrorCode merge_status = mergeSortedLists(list1, list2, &merged_actual);
Note: getMin() gets the minimum value and advances the pointer of the list which has that min value to the next node.
Start after those if checks.
Node ptr=NULL,last;
/* find out current tail of the list */
if (*merged_out!=NULL){
last=*merged_out;
while (last->next!=NULL){
last=last->next;
}
}
int total_len = getListLength(list1) + getListLength(list2);
for (int i = 0; i < total_len; i++)
{
int min = getMin(&list1, &list2);
ptr = malloc(sizeof(*ptr));
if (!ptr)
{
destroyList(*merged_out);
*merged_out=NULL;
return MEMORY_ERROR;
}
ptr->x = min;
ptr->next = NULL;
/* link ptr onto the list */
if (*merged_out==NULL){
/* if the list is empty, make ptr the head of the list */
*merged_out=ptr;
last=*merged_out;
}
else{
last->next = ptr;
last = ptr;
}
}
Please try not to copy and paste this block of code. It may or may not be correct, but try to understand what it did: iterate each time the function is called, in an effort to put last to point at the last element of the list. Therefore merged_out can always point to the head.
#user12986714 I lost my old account, and was told to not to care about the initial value of *merged_out could you update the solution (delete the first while loop and no need for 2 pointers)
Hi I'm new to C and pointers and are having issues trying to implement the below doubly linked list structure. Memory leaks happened in listInsertEnd I believe? I am very confused as to why one work (at least no mem leak in output) and the other one doesn't. I have pasted only parts of the program, any help or explanation is much appreciated.
#include <stdio.h>
#include <stdlib.h>
typedef struct node *Node;
struct node {
int value;
Node next;
Node prev;
};
typedef struct list *List;
struct list {
Node first;
Node last;
int count;
};
Node newNode(int value) {
Node n = malloc(sizeof(*n));
if (n == NULL) fprintf(stderr, "couldn't create new node\n");
n->value = value;
n->next = NULL;
n->prev = NULL;
return n;
}
void listInsertEnd(List newList, int value) {
Node n = newNode(value);
if (newList== NULL) { //no item in list
//why is this giving me memory leaks
newList->first = newList->last = n;
//whereas this doesn't?
newList->first = newList->last = newNode(value);
} else { //add to end
n->prev = newList->last;
newList->last->next = n;
newList->last = n;
}
nList->count++;
}
First of all, talking about memory leaks: there is no direct memory leak in your code. If the leak happens somewhere, it's outside of these functions. It's most probably because you create one or more nodes and then forget to free() them, but this has nothing to do with the two functions you show.
I see that you are using typedef to declare simple pointer types, take a look at this question and answer to understand why that's bad practice and should be avoided: Is it a good idea to typedef pointers?. Also, this particular piece of Linux kernel documentation which explains the issue in more detail.
Secondly, the real problem in the code you show is that you are using pointers after you tested that they are invalid (NULL).
Here:
Node newNode(int value) {
Node n = malloc(sizeof(*n));
if (n == NULL) fprintf(stderr, "couldn't create new node\n");
n->value = value;
// ^^^^^^^^ BAD!
And also here:
if (newList== NULL) {
newList->first = newList->last = n;
// ^^^^^^^^^^^^^^ BAD!
If something is NULL, you cannot dereference it. Change your functions to safely abort after they detect an invalid pointer.
This can be done in multiple ways. Here's an example of correct code:
Node newNode(int value) {
Node n = malloc(sizeof(*n));
if (n == NULL) {
fprintf(stderr, "couldn't create new node\n");
return NULL;
}
n->value = value;
n->next = NULL;
n->prev = NULL;
return n;
}
void listInsertEnd(List newList, int value) {
Node n;
if (newList == NULL) {
return;
// You probably want to return some error value here.
// In that case change the function signature accordingly.
}
n = newNode(value);
if (newList->count == 0) {
newList->first = newList->last = n;
} else { //add to end
n->prev = newList->last;
newList->last->next = n;
newList->last = n;
}
newList->count++;
}
NOTE: the check newList->count == 0 assumes that you correctly increment/decrement the count when adding/removing elements.
This typedef declaration
typedef struct node *Node;
is confusing and presents a bad style. Consider for example this statement
Node n = malloc(sizeof(*n));
somebody can think that here is a typo and should be written
Node *n = malloc(sizeof(*n));
The function
void listInsertEnd(List newList, int value) {
Node n = newNode(value);
if (newList== NULL) { //no item in list
//why is this giving me memory leaks
newList->first = newList->last = n;
//whereas this doesn't?
newList->first = newList->last = newNode(value);
} else { //add to end
n->prev = newList->last;
newList->last->next = n;
newList->last = n;
}
nList->count++;
}
has undefined behavior. If newList is equal to NULL then you are trying to use memory pointed to by a null pointer.
if (newList== NULL) { //no item in list
//why is this giving me memory leaks
newList->first = newList->last = n;
//whereas this doesn't?
newList->first = newList->last = newNode(value);
And initially data members newList->first and newList->last can be equal to NULL. That also can be reason of undefined behavior because the function does not take this into account.
Before changing the function listInsertEnd you should define the function newNode the following way
Node newNode(int value)
{
Node n = malloc(sizeof(*n));
if ( n != NULL )
{
n->value = value;
n->next = NULL;
n->prev = NULL;
}
return n;
}
The function shall not issue any message. It is the caller of the function that decides whether to issue a message if it is required.
In this case the function listInsertEnd can be written the following way
int listInsertEnd(List newList, int value)
{
Node n = newNode(value);
int success = n != NULL;
if ( success )
{
n->prev = newList->last;
if ( newList->first == NULL )
{
newList->first = newList->last = n;
}
else
{
newList->last = newList->last->next = n;
}
++newList->count;
}
return success;
}
Within the main you should create the list the following way
int main( void )
{
struct list list1 = { .first = NULL, .last = NULL, .count = 0 };
// or
// struct list list1 = { NULL, NULL, 0 };
and call the function like
listInsertEnd) &list1, some_integer_value );
I think there is something wrong with my create.
void add(N *p) {
N *current, *start;
current = malloc(sizeof(p));
scanf("%d", ¤t->data);
current->next = NULL;
if (p == NULL) {
p = current;
start = current;
} else {
start->next = current;
start = current;
}
}
I think that my display() is correct.
void display(N *p) {
N *current;
current = p;
while (current != NULL) {
printf("\n%d", current->data);
current = current->next;
}
}
Your malloc(sizeof(p)) only returns enough space for a pointer. You instead want malloc(sizeof(N)).
Also, you need to return the new value of p instead of throwing it away at the end of add(). (Your start has a similar issue; pick one to be the head of your linked list.)
There are problems:
function add() does not allocate the correct amount of memory. Use this method:
current = malloc(sizeof(*current));
The way you are inserting the newly allocated object into the list does not work: you modify p, which is an argument with local scope, and you set start which also has local scope. No side effect is performed on the N pointer is the callers scope.
Your display function is correct, but I would favor adding the newline at the end of the output instead of at the beginning.
Here is an updated version with a better API:
int add(N **headp) {
N *current = calloc(sizeof(*current));
if (current == NULL) {
fprintf(stderr, "cannot allocate memory for new object\n");
return -1;
}
if (scanf("%d", ¤t->data) != 1) {
fprintf(stderr, "cannot read value for new object\n");
return -2;
}
current->next = *headp;
*headp = current;
return 0;
}
void display(const N *list) {
for (const N *p = list; p != NULL; p = p->next) {
printf("%d\n", p->data);
}
}
The add function is used this way from the caller:
#include <stdio.h>
#include <stdlib.h>
typedef struct N {
int data;
struct N *next;
} N;
int main(void) {
N *list = NULL;
for (i = 0; i < 10; i++) {
if (add(&list))
break;
}
display(list);
return 0;
}
please dont press the rep minus button so easily im new here- be nice please
i have slist.h implementing by slist.c
here is the slist.h
#ifndef DBLLIST_H
#define DBLLIST_H
//! The definition of a double linked list node
typedef struct dbllist_node
{
void *data; // Pointer to data of this node
struct dbllist_node *next; // Pointer to next node on list
struct dbllist_node *prev; // Pointer to previous node on list
}dbllist_node_t;
//! The definition of a double linked list
struct dbllist
{
dbllist_node_t *head; // Pointer to head of list
dbllist_node_t *tail; // Pointer to tail of list
unsigned int size; // The number of elements in the list
};
//! double linked list type
typedef struct dbllist dbllist_t;
// you have to use these macros, do not use the inner variables of the list!!
//! Macro to get the head node of a list l
#define dbllist_head(l) l->head
//! Macro to get the tail node of a list l
#define dbllist_tail(l) l->tail
//! Macro to get the size of a list l
#define dbllist_size(l) l->size
//! Macro to get the next node of l
#define dbllist_next(n) n->next
//! Macro to get the prev node of l
#define dbllist_prev(n) n->prev
//! Macro to get the data of node l
#define dbllist_data(n) n->data
//! Specifies whether dbllist_destroy should deallocate or not stored elements
typedef enum { DBLLIST_LEAVE_DATA = 0, DBLLIST_FREE_DATA } dbllist_destroy_t;
/** Initialize a double linked list
\param list - the list to initialize */
void dbllist_init(dbllist_t *);
/** Destroy and de-allocate the memory hold by a list
\param list - a pointer to an existing list
\param dealloc flag that indicates whether stored data should also be de-allocated */
void dbllist_destroy(dbllist_t *,dbllist_destroy_t);
/** Append data to list (add as last node of the list)
\param list - a pointer to a list
\param data - the data to place in the list
\return 0 on success, or -1 on failure */
int dbllist_append(dbllist_t *,void *);
/** Prepend data to list (add as first node of the list)
\param list - a pointer to list
\param data - the data to place in the list
\return 0 on success, or -1 on failure
*/
int dbllist_prepend(dbllist_t *,void *);
/** \brief Remove the specific node from the list.
\param to a pointer to the list
\param pointer to the node that should be removed.
\param dealloc flag that indicates whether to de-allocated the data in the node
\return 0 on success, or -1 on failure
*/
int dbllist_remove(dbllist_t *, dbllist_node_t* ,dbllist_destroy_t);
#endif
and now the slist.c i wrote
my problem is when ever i call the destroy function im facing segmentation fault at the last node.. i can provide main that i wrote too.
#include "slist.h"
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
void dbllist_init(dbllist_t *list)
{ if(list != NULL)
{
dbllist_head(list) = NULL;
dbllist_tail(list) = NULL;
dbllist_size(list) = 0;
}
}
int dbllist_append(dbllist_t *list,void *data)
{
dbllist_node_t *temp = (dbllist_node_t *)malloc(sizeof(dbllist_node_t));
if(temp == NULL)
return -1;
dbllist_data(temp) = data;
if(list!=NULL)
{
if(dbllist_head(list) == NULL)
{
//dbllist_next(temp) = NULL;
dbllist_prev(temp) = NULL;
dbllist_head(list) = temp;
dbllist_tail(list) = temp;
dbllist_size(list)++;
return 0;
}
else
{
dbllist_next(temp) = NULL;
dbllist_prev(temp) = dbllist_tail(list);
dbllist_next(dbllist_tail(list)) = temp;
dbllist_tail(list) = temp;
dbllist_size(list)++;
return 0;
}
}
return -1;
}
int dbllist_prepend(dbllist_t *list,void *data)
{
dbllist_node_t *temp = (dbllist_node_t *)malloc(sizeof(dbllist_node_t));
if(temp == NULL)
return -1;
dbllist_data(temp) = data;
if(list!=NULL)
{
if(dbllist_head(list) == NULL)
{
//dbllist_next(temp) = NULL;
dbllist_prev(temp) = NULL;
dbllist_head(list) = temp;
dbllist_tail(list) = temp;
dbllist_size(list)++;
return 0;
}
else
{
dbllist_next(temp) = dbllist_head(list) ;
dbllist_prev(temp) = NULL;
dbllist_prev(dbllist_head(list)) = temp;
dbllist_head(list) = temp;
dbllist_size(list)++;
return 0;
}
}
return -1;
}
/**
int dbllist_remove(dbllist_t *list, dbllist_node_t* pointer,dbllist_destroy_t dealloc)
{
dbllist_node_t *temp = (dbllist_node_t *)malloc(sizeof(dbllist_node_t));
if(temp == NULL)
return -1;
temp = dbllist_head(list);
if(list != NULL && pointer !=NULL)
{
if(pointer == dbllist_head(list))
{
if(dealloc != DBLLIST_LEAVE_DATA)
free(dbllist_data(pointer));
dbllist_head(list) = NULL;
dbllist_size(list) = 0;
dbllist_tail(list) = NULL;
free(dbllist_head(list));
free(temp);
return 0;
}
if(pointer == dbllist_tail(list))
{
dbllist_tail(list) = dbllist_prev(dbllist_tail(list)) ;
dbllist_next(dbllist_tail(list)) = NULL;
if(dealloc != DBLLIST_LEAVE_DATA)
free(dbllist_data(pointer));
free(temp);
free(pointer);
dbllist_size(list)--;
return 0 ;
}
int tempSize = 1;
for(temp = dbllist_next(temp) ; tempSize< dbllist_size(list); temp = dbllist_next(temp),tempSize++)
if(temp == pointer)
{
dbllist_next(dbllist_prev(temp)) = dbllist_next(temp);
dbllist_prev(dbllist_next(temp)) = dbllist_prev(temp);
if(dealloc != DBLLIST_LEAVE_DATA)
free(dbllist_data(pointer));
free(temp);
free(pointer);
dbllist_size(list)--;
return 0;
}
}
return -1;
}
*/
int dbllist_remove(dbllist_t *list, dbllist_node_t* pointer,dbllist_destroy_t dealloc)
{
if(list == NULL || pointer == NULL )
return -1;
//printf("%d \n",(int)dbllist_data(current));
if( pointer == dbllist_head(list))
{
dbllist_head(list) = dbllist_next(dbllist_head(list));
if(dealloc == DBLLIST_FREE_DATA)
free(dbllist_data(dbllist_prev(dbllist_head(list))));
free(dbllist_prev(dbllist_head(list)));
dbllist_prev(dbllist_head(list)) = NULL;
dbllist_size(list)--;
return 0;
}
if(pointer == dbllist_tail(list))
{
dbllist_tail(list) = dbllist_prev(dbllist_tail(list));
if(dealloc == DBLLIST_FREE_DATA)
free(dbllist_data(dbllist_next(dbllist_tail(list))));
free(dbllist_next(dbllist_tail(list)));
dbllist_next(dbllist_tail(list)) = NULL;
dbllist_size(list)--;
return 0;
}
//int i = 1;
dbllist_node_t *current = dbllist_next(dbllist_head(list));
while(current)
{
if(current == pointer)
{
dbllist_next(dbllist_prev(current)) = dbllist_next(current) ;
dbllist_prev(dbllist_next(current)) = dbllist_prev(current) ;
dbllist_size(list)--;
if(dealloc == DBLLIST_FREE_DATA)
free(dbllist_data(current));
free(current);
current = NULL;
return 0;
}
current = dbllist_next(current);
}
free(current);
return -1;
}
void dbllist_destroy(dbllist_t *list ,dbllist_destroy_t dealloc)
{
//dbllist_node_t *current = (dbllist_node_t *)malloc(sizeof(dbllist_node_t));
//dbllist_node_t *temp = (dbllist_node_t *)malloc(sizeof(dbllist_node_t));
while (dbllist_head(list) != NULL)
{
//dbllist_node_t *current;
dbllist_node_t *temp ;
temp = dbllist_tail(list);
while(temp)
{
dbllist_remove(list,temp , dealloc);
printf("in\n");
temp = dbllist_tail(list);
printf("out \n");
}
//temp = dbllist_head(list);
//dbllist_remove(list,temp , dealloc);
//free(temp);
}
//free(current);
//free(temp);
}
can someone understand the error and explain to me how to fix it
im trying over a feew hours now without success
In this code:
if( pointer == dbllist_head(list))
{
// After next line: list->head points to next node (could be null)
dbllist_head(list) = dbllist_next(dbllist_head(list));
if(dealloc == DBLLIST_FREE_DATA)
// -- If head is now NULL, what happens below? --
free(dbllist_data(dbllist_prev(dbllist_head(list))));
free(dbllist_prev(dbllist_head(list)));
dbllist_prev(dbllist_head(list)) = NULL;
dbllist_size(list)--;
return 0;
}
the right answer is:
if(!dbllist_next(dbllist_head(list)))
{
if(dealloc == DBLLIST_FREE_DATA )
free(dbllist_data(dbllist_head(list)));
free(dbllist_head(list));
dbllist_head(list) = NULL;
dbllist_size(list)--;
return 0;
}
add this before the head part in remove function
because of a null pointer exception i did when in the head of the list.
thanks
In your Remove function dbllist_remove the section that is for the head case(pun intended ;)) tries to free memory that is NULL and not allocated.
The arguments free(dbllist_data(dbllist_prev(dbllist_head(list)))) AND dbllist_data(dbllist_prev(dbllist_head(list))) will not work as you have already removed the next element as well as its pointers. It was freed earlier in your destroy function. So, you cannot rely on the previous pointer actually pointing to anything.
So, I would modify your while loop in the destroy function to wait until head->next is null and then simply delete it outside of the loop and not use the standard remove function. Or modify your head case to take into account when head->next is null.