Почему эта программа на С не дает мне доступ к памяти? - PullRequest
0 голосов
/ 01 января 2019

Я пытаюсь создать базу данных связанных списков, и по какой-то причине программа не позволяет мне получить доступ к памяти, или, по крайней мере, так говорит отладчик.Я использую отладчик GDB, кодовые блоки.

Я уже скомпилировал программу на другом компьютере с той же операционной системой (windows).Работало без нареканий, НО отладчик показал ту же ошибку.

void print_ListEl(ListEl* head)
{
 ListEl* current = malloc(sizeof(ListEl));
 current = head;
 if (head==NULL) exit(EXIT_FAILURE);
 if (current->next==NULL)
 {
     puts("No elements");
     return;
 }
 else
 {
     int i=1;
     while(current->next!=NULL)
     {
         printf("%d.%s\n", i, current->name);
         current=current->next;
         ++i;
     }
 }
 free(current);
}

Используется так:

ListEl* element = malloc(sizeof(ListEl));
print_listEl(element);

Эта функция, по-видимому, вызывает проблему в соответствии с отладчиком.Когда я наблюдаю переменную «current-> next», отладчик говорит: «Не удается получить доступ к памяти по адресу».Если я меняю current-> рядом с current, отладчик все равно показывает ту же функцию, что и вызывающая проблему.Структура ListEl - это обычный обычный связанный список с данными типа char.

 struct ListEl
 {
     char name[MAX_CHAR];
     struct ListEl* next;
 };

Я также использую

typedef struct ListEl ListEl

Заголовки безопасны с ifndef и endif и все они включены, я проверил.

Эта функция вместо того, чтобы ставить «Нет элементов», когда в списке нет элементов, выбрасывает некоторый случайный символ и вылетает из программы.

Ответы [ 2 ]

0 голосов
/ 01 января 2019
  1. Вы не должны malloc для current.Вы немедленно заменяете полученный из него указатель на head и теряете выделение.Позднее free освободит последний элемент списка, но не установит указатель предыдущего элемента на NULL, что приведет к неопределенному поведению, если список будет использован позже.

  2. Вы выделяете память для узла здесь:

    ListEl* element = malloc(sizeof(ListEl));
    

    , но вы никогда не устанавливали ни одно из его значений до вызова print_listEl(element);.Поэтому указатель element->next будет неопределенным, и сравнение с NULL не будет полезным.Вы разыменовываете этот указатель позже в print_listEl, вызывая неопределенное поведение.Всегда инициализировать после malloc:

    ListEl* element = malloc(sizeof(ListEl));
    element->next = NULL;
    memset(element->name, '\0', sizeof(element->name));
    
0 голосов
/ 01 января 2019

может быть

ListEl* current = malloc(sizeof(ListEl));
current = head;

должно быть

ListEl* current = malloc(sizeof(ListEl));
head = current;

иначе зачем делать malloc и сразу его потерять?


Надеюсь, у вас есть дополнительныекод перед

if (current->next==NULL)

, поскольку ток только выделяется, но не инициализируется


Когда я наблюдаю переменную «current-> next», отладчик говорит: «Не удается получить доступ к памятипо адресу ".

Это означает, что current был сломан, потому что, например, он был удален, или вы просто никогда не инициализировали поле next .проблема в том, что вы не даете Минимальный, Полный и Проверяемый пример

Если код действительно такой:

ListEl* element = malloc(sizeof(ListEl));
print_listEl(element);

element-> name или element-> next не инициализируются, поэтому в print_listEl это то же самое

...