#c #pointers #memory #doubly-linked-list
#c #указатели #память #двусвязный список
Вопрос:
Итак, я создаю код для программы с использованием C, который просто выполняет основные задачи связанного списка, такие как создание списка, вставка узла после заданного текущего узла, удаление узла и т.д.
Я использую visual studio 2015, поэтому, когда я попытался протестировать свою функцию вставки после узла, отладив ее и используя visual studio watch для визуализации моего списка и того, правильно ли он вставлял узлы после текущего узла, я получил сообщение об ошибке:
Исключение, выданное при 0x011414CE в chars.exe : 0xC0000005: местоположение чтения 0x00000004 с нарушением доступа.
Необработанное исключение при 0x011414CE в chars.exe : 0xC0000005: местоположение чтения 0x00000004 с нарушением доступа.
Итак, вот мой файл .h с объявлением структуры и списка
#ifndef DLIST_H
#define DLIST_H
typedef struct DListNode_struct {
char *str;
int blankIndex;
int blankLength;
struct DListNode_struct *next;
struct DListNode_struct *prev;
} DListNode;
typedef struct DList_struct {
int size;
DListNode *head;
DListNode *tail;
} DList;
void DListConstruct(DList* list);
void DListInsertAfter(DList* list, DListNode* currNode, DListNode* newNode);
#endif // DLIST_H
итак, вот моя основная функция
#include <stdio.h>
#include <stdlib.h>
#include "dlist.h"
int main() {
DList* list = NULL;
DListNode* currNode = NULL;
DListNode* newNode1 = (DListNode*)malloc(sizeof(DListNode));
DListInsertAfter(list, currNode, newNode1);
return 0;
}
И вот мой файл .c, в котором у меня есть функция insertafter
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dlist.h"
void DListConstruct(DList* list) {
list->head = NULL;
list->tail = NULL;
list->size = 0;
}
void DListInsertAfter(DList* list, DListNode* currNode, DListNode* newNode) {
DListNode* sucNode;
if (list->head == NULL) {
list->head = newNode;
list->tail = newNode;
}
else if (currNode == list->tail) {
list->tail->next = newNode;
newNode->prev = list->tail;
list->tail = newNode;
}
else {
sucNode = currNode->next;
newNode->next = sucNode;
newNode->prev = currNode;
currNode->next = newNode;
sucNode->prev = newNode;
}
}
Я нашел несколько сообщений, связанных с моим вопросом, но все они либо не нацелены на связанные списки, либо не находятся в C.
Итак, кто-нибудь может помочь мне найти, где ошибка?
Заранее спасибо.
Комментарии:
1. Отладчик должен точно указать вам, какая строка кода вызывает ошибку seg. Пожалуйста, укажите это как минимум. Стоит потратить время, чтобы научиться более эффективно использовать отладчик.
Ответ №1:
Вы переходите NULL
к DListInsertAfter
as list
, и первая проверка (list->head == NULL)
завершается неудачей при доступе к нулевому указателю.
Ответ №2:
Dlist after получает список, который равен НУЛЮ, поэтому list->head
проблема заключается в том, что происходит. Поскольку оно не существует!
Сначала вам нужно выделить список.
#include <stdio.h>
#include <stdlib.h>
#include "dlist.h"
int main() {
DList* list = NULL;
DListNode* currNode = NULL;
DListNode* newNode1 = (DListNode*)malloc(sizeof(DListNode));
DList* list = (void*)malloc(sizeof(DList));
DListInsertAfter(list, currNode, newNode1);
return 0;
}
Комментарии:
1. Я думаю, вы пытались выделить жирным шрифтом строку кода в Markdown; вы не можете этого сделать, так что теперь похоже, что вы немного довольны звездочками, хаха…
2. Упс, я спешил ответить на его вопрос, но, похоже, некоторые другие люди ответили раньше, чем я: D
Ответ №3:
оператор стрелки ->
является синтаксическим сахаром для разыменования в сочетании с доступом к элементу структуры. Поэтому строка
if (list->head == NULL) {
совпадает с
if ((*list).head == NULL) {
При вызове DListInsertAfter()
вы передаете указатель на list
параметр, который инициализируется NULL
. Поэтому вы разыменовываете NULL
указатель, что, вероятно, вызывает сбой. В какой-то момент вам нужно выделить память для вашей DList
структуры, прежде чем пытаться получить к ней доступ.