Изолировал ошибку сегмента — но почему это происходит?

#c #segmentation-fault

#c #ошибка сегментации

Вопрос:

Используя отладчик DevC (все еще новичок в нем), я почти уверен, что изолировал сценарий segfault, но я понятия не имею, почему это происходит.

 void LinkedList::Add(const char *Word){
    ListNode *newNode = new ListNode;
    strcpy(newNode->Word, Word);
    newNode->Next = NULL;
    ...
}
  

Ошибка сегмента возникает в «newNode-> Next = NULL;». Однако, если я удалю strcpy над ним, ошибка segfault не произойдет (но это означает, что мой newNode-> Word пуст)

РЕДАКТИРОВАТЬ: извините, ребята, вот ListNode:

 struct ListNode
{
    char *Word;
    LNodePtr Next;
};
  

Комментарии:

1. Нам нужно увидеть определение ListNode.

2. Вероятно, эту проблему можно решить, если использовать std::string вместо char * для представления строк. В этом случае вы выполняете простое назначение.

3. Можете ли вы опубликовать структуру ListNode ?

4. Для чего вы выделяете память newNode->Word ?

5. Хотя это и не вызывает проблемы, я изменю свой strcpy на strncpy(newNode-> Word, Word, cMaxLen); для безопасности. Спасибо за подсказку

Ответ №1:

Если Word элемент является указателем, ваша strcpy память перезапишет нераспределенную память.

После этого большинство операций может завершиться неудачей.

Использование std::string вместо const char* во многих местах спасет вас.

Комментарии:

1. Вы предполагаете, что в ListNode конструкторе для Word указателя не выделено памяти.

2. @Naveen — Да, или недостаточно памяти. Просмотр const char *Word параметра просто заставляет меня поверить, что другой Word выглядит так же. Тот факт, что он инициализирует элементы в Add , предполагает, что конструктор мало что делает.

Ответ №2:

Вы не выделили никакой памяти для Word указателя в ListNode структуре. Без этого он указывает на какое-то случайное местоположение, и всякий раз, когда вы пытаетесь выполнить запись в это местоположение (используя strcpy ), вы получите нарушение доступа. Самый простой способ решить эту проблему — использовать std::string класс и избавиться от всего ручного управления памятью.

Если вы действительно хотите использовать char* , то напишите конструктор, для ListNode которого принимается const char* параметр (не забудьте, однако, объявить его как explicit ) и используйте strlen для определения длины входной строки. Затем выделите len 1 (дополнительный один char для НУЛЕВОГО ограничителя) символы и сохраните адрес в Word указателе. После этого вы можете сделать strncpy .

Комментарии:

1. Теперь я вижу свою проблему, спасибо. К сожалению, мне пока придется придерживаться ручного управления памятью, поскольку это диктует мое назначение.

2. Я только что прочитал вашу правку, я попробую это! На данный момент просто добавьте «newNode-> Word = new char[cMaxLen]», прежде чем strncpy заработает. Значение cMaxLen равно 100. Я понимаю, что это делает бессмысленной динамичность, но это позволит мне пока поработать с остальной частью программы.

3. @Paul: не забудьте освободить память в деструкторе, иначе произойдет утечка.

Ответ №3:

strcpy это нормально, но очень опасно, оно создает копию ваших символов, пока не достигнет . Если ваш Word файл не содержит никакого , он скопирует много материала в ваш newNode->Word указатель.

Другая потенциальная опасность заключается в том, как вы инициализируете newNode->Word , выделили ли вы достаточно места для копирования строки?

Ответ №4:

выдвигаю предположение.. Я бы рискнул предположить, что в вашей ListNode реализации Word это char* , и оно не инициализировано для указания на допустимый блок памяти (может быть null) — strcpy() не выделяет пространство автоматически, оно предполагает, что в месте назначения достаточно места. И здесь он пытается скопировать строку в нулевой указатель (или неинициализированный указатель) — отсюда ошибка segfault…