Pete Jodo
Pete Jodo

Reputation: 463

C function with data structure pointer parameter

I have a program that creates a sorted linked list which after testing it works in creating the list. My problem comes when attempting to remove an element in the list. The types are hidden which in the code you'll see the parameter void* newObj and the struct has a function pointer it uses to make the actual comparison.

My code segfaults and I believe it's because the head of the list isn't updating so a pass-by-value issue but I'm not sure how to fix it.

Function:

int SLRemove(SortedListPtr list, void *newObj)
{
    SortedListPtr temp;
    SortedListPtr temp2;

    if(list->CompareFcn(newObj, list->value) == 0)
    {
        if(list->flag == 1)
        {
            return 0;
        }
        temp = list;
        list = list->next;
        printf("(if)Address of object: %p with value %d, freed.\n", temp, *(int*)temp->value);
        free(temp);
        printf("New head of list is, address: %p, value: %d.\n", list, *(int*)list->value);
        return 1;
    }
    for (temp = list; temp != NULL; temp = temp->next)
    {
        printf("Address of TEMP: %p\n", temp);
        temp2 = temp->next;
        if(temp2->CompareFcn(newObj, temp2->value) == 0)/*value == *newObj*/
        {
            temp->next = temp2->next;
            printf("(loop)Address of object: %p, freed.\n", temp2);
            free(temp2);
            return 1;
        }
    }

    return 0;
}

Caller:

for (icount = 1; icount <= 3; icount += 1)
    {
        *ptr[icount-1] = icount;
        printf("Removing...\n");
        printf("Current head of list to be removed, address: %p, value: %d.\n", integerList, *(int*)integerList->value);
        if (SLRemove(integerList, ptr[icount-1]) == 1)
        {
            printf("SLRemove number %d, success!\n\n", icount);
            free(ptr[icount-1]);
        }
        else
        {
            printf("SLRemove number %d failed!\n\n", icount);
        }
    }

Valgrind:

Removing...
Current head of list to be removed, address: 0x51f1040, value: 1.
Comparing newObj: 1 and item: 1. Returning 0.
(if)Address of object: 0x51f1040 with value 1, freed.
New head of list is, address: 0x51f1140, value: 2.
SLRemove number 1, success!

==23304== Invalid read of size 8
==23304==    at 0x400826: main (main.c:63)
==23304==  Address 0x51f1040 is 0 bytes inside a block of size 32 free'd
==23304==    at 0x4C2A82E: free (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==23304==    by 0x400B8D: SLRemove (sorted-list.c:176)
==23304==    by 0x400805: main (main.c:60)
==23304== 

Upvotes: 0

Views: 331

Answers (1)

Vaughn Cato
Vaughn Cato

Reputation: 64308

You are modifying list inside SLRemove(), but since it is passed by value, that change never gets back to the caller. Try

int SLRemove(SortedListPtr *list_ptr, void *newObj)
{
  SortedListPtr list = *list_ptr;
  .
  .
  .
    *list_ptr = list;
    return 1;
  .
  .
  .
}

When you call it, use:

    if (SLRemove(&integerList, ptr[icount-1]) == 1)

Upvotes: 1

Related Questions