1

I want to delete node from singly linked list using only one local pointer variable in C, the debugger stops on the free(cur) of the delete function without any error, but it runs normally in free(cur->next), why is this? What error in this code section?

struct node
{
    int val;
    struct node *next;
};

typedef struct
{
    struct node *header;
} List;

void add(List *pList, int val)
{
    struct node *new_node = malloc(sizeof pList->header);
    if (new_node == NULL)
    {
        exit(EXIT_FAILURE);
    }

    new_node->val = val;
    new_node->next = pList->header;
    pList->header = new_node;
}

void delete(List *pList, int val)
{
    struct node *cur = pList->header;
    if (cur != NULL)
    {
        if (cur->val == val)
        {
            struct node *temp = cur->next;
            //debug stop in free(cur) without any error,why?
            free(cur);
            cur = temp;
        }
        else
        {
            while (cur->next != NULL && cur->next->val != val)
            {
                cur = cur->next;
            }

            if (cur->next != NULL)
            {
                struct node *temp = cur->next->next;
                // run normally, why?
                free(cur->next);
                cur->next = temp;
            }
        }
    }
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
Zero100100
  • 11
  • 2

1 Answers1

2

There is a problem in the add function: you pass the size of a pointer to malloc instead of the size of the node structure. A safer way to always pass the correct size is this:

    struct node *new_node = malloc(sizeof *new_node);

As coded, the memory allocated is too small and you have undefined behavior when you initialize the structure, writing beyond the end of the allocated block.

There is another problem in the delete() function: you do not update pList->header when you free the first node.

Here is a modified block:

struct node {
    int val;
    struct node *next;
};

typedef struct {
    struct node *header;
} List;

void add(List *pList, int val) {
    struct node *new_node = malloc(sizeof(*new_node));
    if (new_node == NULL) {
        exit(EXIT_FAILURE);
    }

    new_node->val = val;
    new_node->next = pList->header;
    pList->header = new_node;
}

void delete(List *pList, int val) {
    struct node *cur = pList->header;
    if (cur != NULL) {
        if (cur->val == val) {
            pList->header = cur->next;
            free(cur);
        } else {
            while (cur->next != NULL) {
                struct node *temp = cur->next;
                if (temp->val == val) {
                    cur->next = temp->next;
                    free(temp);
                    break;
                }
                cur = temp;
            }
        }
    }
}
chqrlie
  • 131,814
  • 10
  • 121
  • 189
  • Thanks, malloc(sizeof(*new_node)) is correct. [link](https://stackoverflow.com/questions/605845/do-i-cast-the-result-of-malloc) – Zero100100 Jan 31 '22 at 10:38