<list> выдает необработанное исключение при вызове push_front () - PullRequest
0 голосов
/ 13 июля 2009

Я работаю над графическим интерфейсом в SDL. Я создал ведомый / мастер-класс, который содержит std :: list указателей на его собственные ведомые, чтобы создать иерархию в GUI (окно, содержащее кнопки. Button a label и т. Д.). Некоторое время он работал нормально, пока я не отредактировал совершенно другой класс , который напрямую не влияет на подчиненный / мастер-класс. Вызов list.push_front () в старом ведомом / мастер-классе теперь выдает следующую ошибку при отладке в VS C ++ 2008 express, и я не могу найти причину.

"Необработанное исключение в 0x00b6decd в workbench.exe: 0xC0000005: доступ нарушение места чтения 0x00000004 ".

* workbench.exe - это мой проект. Исключение возникает в методе _Insert в коде списка в строке 718:

_Nodeptr _Newnode = _Buynode(_Pnode, _Prevnode(_Pnode), _Val);

Список создается в определении класса master / slave, а класс slave / master создается в куче для вставки в список slave другого master. Список, который вылетает, является пустым, когда вызывается push_front (), но он занимает второе место в иерархии, поэтому он работал один раз. Как я уже сказал, раньше все работало нормально, и ведомый / мастер-класс не был изменен, чтобы вызвать ошибку. Новый класс также использует списки. Может ли использование нескольких списков вызвать конфликты? Могу ли я случайно испортить кучу? Любая помощь и советы, что я мог бы найти, приветствуется.

P.S Код довольно большой, поэтому я думаю, что лучше его не включать. Тем более, что я не совсем уверен, что именно является причиной ошибки. Извините, если немного не хватает

Обновление: Я заменил push_front () на создание итератора и использование insert (). Результатом был итератор, указывающий на «baadf00d» после назначения list.begin (). Насколько я могу судить, baadf00d - это некоторый указатель ошибки / NULL, который VS использует для объектов, которым ничего не было назначено. Я полагаю, это еще один признак того, что список поврежден?

Ответы [ 5 ]

3 голосов
/ 13 июля 2009

Обычно подобные ошибки с адресами, такими как 0x00000004, указывают на разыменование пустого указателя, например,

 struct point {
    int x;
    int y;
 };

 struct point *pt = NULL;
 printf("%d\n", pt->y);

может создать такую ​​ошибку.

Не пахнет для меня повреждением кучи, обычно эти ошибки, как правило, более тонкие, я уверен, что это случай с нулевым указателем. Я пошел бы вверх по стеку вызовов и стал бы искать нулевые указатели, мог бы быть членом объекта, который вы помещаете в начало списка, или самого объекта. Если вы действительно думаете, что это проблема повреждения кучи, вы можете использовать gflags, что бесплатно, чтобы включить кучу страниц и т. П., Что позволит вам раньше обнаружить повреждение кучи, надеюсь, что это случится чем побочные эффекты, которые он вызывает позже.

0 голосов
/ 30 июля 2009

Наконец, просмотрев каждый закоулок, я нашел ошибку! Это было совершенно неожиданно, и я чувствую себя немного смущенным по этому поводу.

Я недавно переставил файлы. До этого у меня были общие классы в одной папке, а файлы пользовательского интерфейса - в подпапках. Я скопировал файлы GUI в основную папку и подумал, что все правильно связал, но, очевидно, я пропустил одну строку, и мне никогда не приходило в голову, когда она начала выдавать. Моя библиотека была скомпилирована, так как она была связана, но моя программа тестирования не была ... она просто смотрела на старые заголовочные файлы! С самого начала работал нормально, поскольку заголовки были одинаковыми, но потом я отредактировал один, и объявленный в нем класс начал вести себя забавно, как уже упоминалось, очевидно, поскольку он больше не мог распознать эту чертову вещь. Это выглядело как испорченная память, вот что я искал.

Извлеченный урок: не держите две версии близко друг к другу или вообще.

0 голосов
/ 13 июля 2009

По моим предположениям, из-за комбинации _Prevnode и push_front видно, что список был поврежден ранее, возможно, из-за неправильного использования итератора. Другой способ испортить список - удалить элемент из пустого списка. Убедитесь, что в VS2008 включена отладка итератора. Он поймает много проблем намного раньше.

0 голосов
/ 13 июля 2009

Учитывая отсутствие кода, лучшее, что я могу сделать, это дать вам несколько сценариев, о которых я могу думать:

Наиболее очевидным и трудным для поиска является повреждение памяти. По списку ходили, поэтому добавление к элементу означает, что список манипулирует дерьмовой памятью. Вы можете проверить это, перемещая переменные в их объявлении и изменяя порядок присваивания. Если из-за этого ошибка исчезнет или переместится, вы столкнулись с проблемой памяти. Вы также можете попробовать изменить список на вектор и посмотреть, что он делает.

Вторая возможность состоит в том, что у вас есть список указателей / ссылок, и элементы освобождаются до / после помещения в стек. Это может легко произойти, если вы поместите адрес объекта стека в список, размещенный в другом месте. Вы говорите, что создали объект в куче, поэтому я думаю, что это не так.

0 голосов
/ 13 июля 2009

Возможно, вы вызвали переполнение буфера или другое повреждение памяти в исходном коде, которое до сих пор не проявлялось Нет риска конфликта между различными экземплярами списка, и, как вы говорите, новый код не взаимодействует со старым кодом. Поэтому, за исключением магии, вы кодировали ошибку.

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