[英]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 行的函数dequeue
中free
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);
通过在入enqueue
和dequeue
的入口和返回处添加 debug printf
s,我发现对dequeue
的第一次调用不会导致错误并在else
分支中返回。 错误发生在对dequeue
的第二次调用中,该调用也在else
分支中返回。 显然,在第一次dequeue
调用中,您free
了一个将被使用的节点,并在第二次调用中free
d。
我没有详细分析你的程序,但我想在dequeue
free
old
和cur
是错误的。
使用调试器逐步运行您的程序,并考虑列表中的节点是如何连接的以及何时必须free
哪个节点。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.