简体   繁体   中英

Segmentation fault and dereferencing pointer

I'm working on a project for school and I have to implement a queue. I wrote some very simple tests in my main.c file to see if everything worked fine, but I get two errors I don't know how to fix, and I might need a little help from you guys !

First error

The first error I get is a Segmentation fault (core dumped) . I know it has to do with a memory access problem, but honestly I don't know what I did wrong. Is there a simple way to debug segfaults in c ?

Second error

By the way, when I uncomment line 9 of my main.c

printf("One node added, size = %d\n",my_queue->size);

I get another error message:

main.c: In function ‘main’:
main.c:9:47: error: dereferencing pointer to incomplete type ‘queue_t’ {aka ‘struct queue’}
    9 |  printf("One node added, size = %d\n",my_queue->size);
      |                                               ^~

I found out that this error occurs when you try to dereference a struct that hasn't been defined (or declared) yet. This message surprises me because I did declare my type queue_t in my header file queue.h and I did define it in my queue.c file.

You can find all the files i'm talking about on this repo

Thanks a lot for your help and have a good day !

Diego

The compilation error dereferencing pointer to incomplete type 'queue_t' results from dereferencing a pointer to queue_t in main which is an incomplete type AKA opaque type.

The API in queue.h is designed to hide the definition of the structure queue_t from the caller. The calling functions are supposed to use a pointer to this structure only. So the caller is not supposed to know that there is a structure field size .

The clean way to solve this would be to add a getter function to the API to return the requested value. The function should be declared in queue.h and implemented in queue.c , eg

int get_size(queue_t *queue)
{
    int size = -1; /* error return value */
    if(queue != NULL)
    {
        size = queue->size;
    }
    return size;
}

(As a hack you could add a copy of the structure definition to main.c . I don't recommend this. )


To check the segmentation fault I compiled the program with

gcc -Wall -Wextra -pedantic main.c queue.c -o main

Running the program with valgrind as

valgrind ./main

I get several error messages

==25539== Memcheck, a memory error detector
==25539== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
==25539== Using Valgrind-3.15.0 and LibVEX; rerun with -h for copyright info
==25539== Command: ./main
==25539== 
First node added had value 42
==25539== Invalid read of size 4
==25539==    at 0x1092FC: dequeue (queue.c:45)
==25539==    by 0x109200: main (main.c:14)
==25539==  Address 0x4a5a0e8 is 8 bytes inside a block of size 16 free'd
==25539==    at 0x483BA3F: free (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==25539==    by 0x1093AE: dequeue (queue.c:60)
==25539==    by 0x1091E1: main (main.c:13)
==25539==  Block was alloc'd at
==25539==    at 0x483A7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==25539==    by 0x10926D: enqueue (queue.c:25)
==25539==    by 0x1091C4: main (main.c:10)
==25539== 
==25539== Invalid read of size 8
==25539==    at 0x109359: dequeue (queue.c:54)
==25539==    by 0x109200: main (main.c:14)
==25539==  Address 0x4a5a0e0 is 0 bytes inside a block of size 16 free'd
==25539==    at 0x483BA3F: free (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==25539==    by 0x1093AE: dequeue (queue.c:60)
==25539==    by 0x1091E1: main (main.c:13)
==25539==  Block was alloc'd at
==25539==    at 0x483A7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==25539==    by 0x10926D: enqueue (queue.c:25)
==25539==    by 0x1091C4: main (main.c:10)
==25539== 
==25539== Invalid read of size 8
==25539==    at 0x109382: dequeue (queue.c:57)
==25539==    by 0x109200: main (main.c:14)
==25539==  Address 0x4a5a0e0 is 0 bytes inside a block of size 16 free'd
==25539==    at 0x483BA3F: free (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==25539==    by 0x1093AE: dequeue (queue.c:60)
==25539==    by 0x1091E1: main (main.c:13)
==25539==  Block was alloc'd at
==25539==    at 0x483A7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==25539==    by 0x10926D: enqueue (queue.c:25)
==25539==    by 0x1091C4: main (main.c:10)
==25539== 
==25539== Invalid free() / delete / delete[] / realloc()
==25539==    at 0x483BA3F: free (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==25539==    by 0x1093A2: dequeue (queue.c:59)
==25539==    by 0x109200: main (main.c:14)
==25539==  Address 0x4a5a0e0 is 0 bytes inside a block of size 16 free'd
==25539==    at 0x483BA3F: free (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==25539==    by 0x1093AE: dequeue (queue.c:60)
==25539==    by 0x1091E1: main (main.c:13)
==25539==  Block was alloc'd at
==25539==    at 0x483A7F3: malloc (in /usr/lib/x86_64-linux-gnu/valgrind/vgpreload_memcheck-amd64-linux.so)
==25539==    by 0x10926D: enqueue (queue.c:25)
==25539==    by 0x1091C4: main (main.c:10)
==25539== 
Second node added had value 43
==25539== 
==25539== HEAP SUMMARY:
==25539==     in use at exit: 16 bytes in 1 blocks
==25539==   total heap usage: 5 allocs, 5 frees, 1,088 bytes allocated
==25539== 
==25539== LEAK SUMMARY:
==25539==    definitely lost: 16 bytes in 1 blocks
==25539==    indirectly lost: 0 bytes in 0 blocks
==25539==      possibly lost: 0 bytes in 0 blocks
==25539==    still reachable: 0 bytes in 0 blocks
==25539==         suppressed: 0 bytes in 0 blocks
==25539== Rerun with --leak-check=full to see details of leaked memory
==25539== 
==25539== For lists of detected and suppressed errors, rerun with: -s
==25539== ERROR SUMMARY: 4 errors from 4 contexts (suppressed: 0 from 0)

Apparently you have already free da node in function dequeue at line 60

            free(cur);

and you access this node at line 45

        int tbr = q->tail->value; //value to be returned

and line 54

                cur = cur->next;

and line 57

            cur->next = old->next;

Then at line 59 you try to free this block again

            free(old);

By adding debug printf s at the entry and return of enqueue and dequeue I found out that the first call to dequeue doesn't result in an error and returns in the else branch. The errors occur in the second call to dequeue which also returns in the else branch. Apparently in the first call to dequeue you free a node that will be used and free d in the second call.

I didn't analyze your program in detail, but I guess that it is wrong to free both old and cur in dequeue .

Run your program step by step using a debugger and think about how the nodes of your list are connected and when you have to free which node.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM