When I run the program it works except when I delete a fairly large number such as 100 or above, whenever I input anything remotely as large as that number I get the Heap use after free error. The terminal is saying it is caused by line 53 in insert()
which is this line, tail->next = newNode;
. I know keeping head and tail pointers as global variables are not the best way to write it, but I will change it once I get this to work.
void insert(int nData) {
struct Node *newNode = (struct Node*)malloc(sizeof(struct Node) 10);
newNode->data = nData;
newNode->next = NULL;
if(checkDuplicates(nData)==1){
return;
}else{
if(head == NULL){
head = newNode;
tail = newNode;
}
else {
tail->next = newNode;
tail = newNode;
}
}
}
void delete(int n){
if(head -> data==n){
struct Node *tempHead = head;
head= head -> next;
free(tempHead);
return;
} else{
struct Node *current = head;
struct Node *prev = NULL;
while(current!=NULL&¤t->data!=n){
prev = current;
current = current -> next;
}
if(current==NULL) return;
prev->next = current->next;
free(current);
}
}
CodePudding user response:
There is a possible case where tail->next = newNode
would be executed on a freed node: that happens when earlier on you called delete
and that deleted the tail node in the list. In that case your code does not adjust the value of tail
.
So in delete
change:
head = head -> next;
to:
head = head -> next;
if (head == NULL) {
tail == NULL;
}
And in the else
block change:
prev->next = current->next;
free(current);
to:
prev->next = current->next;
if (tail == current) {
tail = prev;
}
free(current);
CodePudding user response:
For starters the function insert
can produce a memory leak because at first a memory is allocated
struct Node *newNode = (struct Node*)malloc(sizeof(struct Node) 10);
(moreover it is unclear what the magic number 10
means in this expression sizeof(struct Node) 10
). And then if the condition of the if statement
if(checkDuplicates(nData)==1){
return;
evaluates to logical true the function exits without freeing the allocated memory.
You need at first to check whether the value is not already present in the list and only after that to allocate memory for the new node.
As for the reason of the error then it seems the reason of the error is inside the function delete
. The function does not reset the pointer tail when a single node is present in the list or when the node pointed to by the pointer tail is removed.
And apart from this even the first statement of the function
if(head -> data==n){
can invoke undefined behavior when the function is called for an empty list.
The function should be defined the following way
int delete( int n )
{
struct Node *current = head;
struct Node *prev = NULL;
while ( current != NULL && current->data != n )
{
prev = current;
current = current->next;
}
int success = current != NULL;
if ( success )
{
if ( prev == NULL )
{
head = head->next;
if ( head == NULL ) tail = NULL;
}
else
{
prev->next = current->next;
if ( prev->next == NULL ) tail = prev;
}
free( current );
}
return success;
}