Ошибка сегментации и разыменование указателя - PullRequest
0 голосов
/ 31 марта 2020

Я работаю над проектом для школы, и мне нужно реализовать очередь. Я написал несколько очень простых тестов в своем основном файле. c, чтобы проверить, все ли работает нормально, но я получаю две ошибки, которые не знаю, как исправить, и мне, возможно, понадобится небольшая помощь от вас, ребята!

Первая ошибка

Первая ошибка, которую я получаю - Segmentation fault (core dumped). Я знаю, что это связано с проблемой доступа к памяти, но, честно говоря, я не знаю, что я сделал не так. Есть ли простой способ отладки segfaults в c?

Вторая ошибка

Кстати, когда я раскомментирую строку 9 моего основного. c

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_t в своем заголовочном файле queue.h и определил его в своей очереди. c file.

Вы можете найти все файлы, о которых я говорю это репо

Большое спасибо за помощь и хорошего дня!

D iego

1 Ответ

0 голосов
/ 31 марта 2020

Ошибка компиляции dereferencing pointer to incomplete type ‘queue_t’ возникает в результате разыменования указателя на queue_t в main, который является непрозрачным типом непрозрачного типа AKA.

API в queue.h предназначен для скрытия определения структура queue_t от звонящего. Вызывающие функции должны использовать указатель только на эту структуру. Таким образом, вызывающий объект не должен знать, что существует структурное поле size.

. Чистым способом решения этой проблемы является добавление функции getter в API для возврата запрошенного значения. Функция должна быть объявлена ​​в 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. Я не t рекомендую это. )


Чтобы проверить ошибку сегментации, я скомпилировал программу с помощью

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)

Очевидно, у вас уже есть free da-узел в функции dequeue в строке 60

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

Путем добавления отладки printf s при вводе и возврате enqueue и dequeue я обнаружил, что первый вызов dequeue не приводит к ошибке и возвращает в else филиал. Ошибки возникают во втором вызове dequeue, который также возвращается в ветке else. Видимо, при первом вызове dequeue вы free узел, который будет использоваться, и free d во втором вызове.

Я не анализировал вашу программу подробно, но, думаю, это неправильно free и old и cur в dequeue.

Запускать программу шаг за шагом, используя отладчик, и подумать о том, как узлы вашего списка связаны и когда вам нужно free какой узел.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...