簡體   English   中英

分段錯誤和取消引用指針

[英]Segmentation fault and dereferencing pointer

我正在為學校做一個項目,我必須實現一個隊列。 我在 main.c 文件中編寫了一些非常簡單的測試,看看是否一切正常,但是我遇到了兩個我不知道如何修復的錯誤,我可能需要你們的幫助!

第一個錯誤

我得到的第一個錯誤是Segmentation fault (core dumped) 我知道這與內存訪問問題有關,但老實說我不知道​​我做錯了什么。 有沒有一種簡單的方法來調試 c 中的段錯誤?

第二個錯誤

順便說一句,當我取消注釋 main.c 的第 9 行時

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

我收到另一條錯誤消息:

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);
      |                                               ^~

我發現當您嘗試取消引用尚未定義(或聲明)的結構時會發生此錯誤。 這條消息讓我感到驚訝,因為我確實在頭文件 queue.h 中聲明了我的類型 queue_t 並且我確實在我的 queue.c 文件中定義了它。

你可以在這個repo上找到我正在談論的所有文件

非常感謝您的幫助,祝您有美好的一天!

迭戈

dereferencing pointer to incomplete type 'queue_t'的編譯錯誤是由於dereferencing pointer to incomplete type 'queue_t' main指向queue_t的指針而導致的, main是不完整的類型 AKA 不透明類型。

queue.h的 API 旨在對調用者隱藏結構queue_t的定義。 調用函數應該只使用指向該結構的指針。 所以調用者不應該知道有一個結構字段size

解決這個問題的干凈方法是向 API 添加一個 getter 函數以返回請求的值。 該函數應該在聲明queue.h和實施queue.c ,如

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

(作為一個黑客,您可以將結構定義的副本添加到main.c我不推薦這樣做。


為了檢查分段錯誤,我編譯了程序

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

使用valgrind作為運行程序

valgrind ./main

我收到幾條錯誤消息

==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)

顯然你已經在第 60 行的函數dequeuefree da 節點

            free(cur);

然后您在第 45 行訪問此節點

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

和第 54 行

                cur = cur->next;

和第 57 行

            cur->next = old->next;

然后在第 59 行,您再次嘗試free此塊

            free(old);

通過在入enqueuedequeue的入口和返回處添加 debug printf s,我發現對dequeue的第一次調用不會導致錯誤並在else分支中返回。 錯誤發生在對dequeue的第二次調用中,該調用也在else分支中返回。 顯然,在第一次dequeue調用中,您free了一個將被使用的節點,並在第二次調用中free d。

我沒有詳細分析你的程序,但我想在dequeue free oldcur是錯誤的。

使用調試器逐步運行您的程序,並考慮列表中的節點是如何連接的以及何時必須free哪個節點。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM