1

I have a List, each node in the list holds a char *data field which has to be malloc'd with the node itself, but when I try to free that data the console just stops, it doesn't crash, their is no error, nothing. But if I comment it out and only free the list node it works fine.

Am I doing this right?

void removeSpecificData(List *list, char *course)
{
    ListNodePtr currentNode = list->head;
    ListNodePtr previousNode = NULL;

    while (currentNode != NULL)
    {
        if (strcmp(currentNode->data, course) == 0)
        {
            ListNodePtr nodeToFree = currentNode;

            if (previousNode == NULL)
            {
                list->head = currentNode->nextNode;
                currentNode = list->head;
            }
            else
            {
                previousNode->nextNode = currentNode->nextNode;
                currentNode = previousNode->nextNode;
            }

            printf("Free Data");
            free(nodeToFree->data);
            printf("Free Node");
            free(nodeToFree);
        }
        else
        {
            previousNode = currentNode;
            currentNode = currentNode->nextNode;
        }
    }
}

Here's my createListNode function incase it's necessary to view.

ListNodePtr createListNode(char *newCourse)
{
    ListNodePtr newNode = (ListNodePtr)malloc(sizeof(struct ListNode));
    newNode->data = (char *)malloc(sizeof(strlen(newCourse) + 1));
    strcpy(newNode->data, newCourse);
    newNode->nextNode = NULL;

    return newNode;
}

Thanks in advance.

  • The first function shall not compile because the variable nodeToFree is neither declared nor assigned. So this statement free(nodeToFree); does not make sense.:) – Vlad from Moscow Apr 06 '18 at 15:44

3 Answers3

3

The following line is incorrect.

newNode->data = (char *)malloc(sizeof(strlen(newCourse) + 1));

The sizeof() part is not right. If the length of the string is greater than sizeof(size_t), you end up allocating less memory than you need. The call to strcpy following it will use memory beyond what you allocated. As a consequence, your program will have undefined behavior.

Use

newNode->data = malloc(strlen(newCourse) + 1);

See Do I cast the result of malloc?

R Sahu
  • 204,454
  • 14
  • 159
  • 270
2

The allocation size is incorrect. It's detected by the system only when attempting to free the memory (corrupt memory list).

Why not just:

newNode->data = strdup(newCourse);

it would allocate the proper size (unlike your attempt) and would copy the string at the same time (no need for malloc and strcpy)

Jean-François Fabre
  • 137,073
  • 23
  • 153
  • 219
  • 2
    "Why not" --> High portability precludes using `strdup()`. `malloc()` and `strcpy()` are both in the the standard C library. `strdup()` is not. Yet `strdup()` is very commonly available - to the point of being ubiquitous. – chux - Reinstate Monica Apr 06 '18 at 15:39
0

For starters the function removeSpecificData at least has a typo or a bug because there is absent a declaration of the variable nodeToFree and neither value was assigned to the variable.

So this statement

free(nodeToFree);

does not make sense.

Also in this else block the second expression statement does not make sense.

    else
    {
        previousNode->nextNode = currentNode->nextNode;
        currentNode = previousNode->nextNode;
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
    }

The function is too complicated. It can be written much simpler. For example

void removeSpecificData(List *list, const char *course)
{
    ListNodePtr *currentNode = &list->head;

    while ( *currentNode != NULL && strcmp( ( *currentNode )->data, course) != 0 )
    {
        currentNode = &( *currentNode )->nextNode;
    }

    if ( *currentNode != NULL )
    {
        ListNodePtr tmp = *currentNode;
        *currentNode = ( *currentNode )->nextNode;

        free( tmp->data );
        free( tmp );
    }
}    

As for the function createListNode then the expression

strlen(newCourse) + 1

has the type size_t. So the value of the expression that by the way is not evaluated:)

sizeof(strlen(newCourse) + 1)

is equivalent to the expression

sizeof( size_t )

and is equal to 4 or 8 depending on the definition of the type size_t.

You nedd to write just

newNode->data = (char *)malloc( strlen(newCourse) + 1 );
Vlad from Moscow
  • 301,070
  • 26
  • 186
  • 335
  • nodeToFree is declared closest to its first use, inside the if statement when the course is found, the change to mallocing fixed the issue though, thank you. :) – Grant Upson Apr 06 '18 at 23:25