Home > Back-end >  Program throws heap use after free error when I perform certain test cases
Program throws heap use after free error when I perform certain test cases

Time:10-16

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&&current->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;
}
  • Related