繁体   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