|
1 / 1 / 0
Регистрация: 21.11.2017
Сообщений: 24
|
|||||||||||
Работа с std::vector содержащим указатели21.11.2017, 12:27. Показов 2711. Ответов 49
Метки нет (Все метки)
Привет! Я долгое время находился в ридонли, решил всё же задать вопрос, так как проблему не получается решить самостоятельно, из-за нехватки знаний по всей видимости. Оговорюсь, что на момент как я решил выучить c++, я уже хорошо знал несколько языков в том числе python java php и так далее.
Пишу небольшую игру на С++, кодовая база получилась уже сейчас довольно большая (для меня как только-только изучающего с++). Всё бы хорошо кроме одного момента. В программе есть вектор содержащий все сущности игры вида:
и вызова у каждой из них ->update(), всё в принципе стандартно. Всё работает хорошо и как нужно кроме одного момента: Периодически абсолютно в неясные для меня моменты (то есть какой либо зависимости у этих событий нет) получаю segfault либо на ->update(); (если я компилирую в g++) либо на сортировке объектов, в случае добавления новых сущностей для сохранения порядка отрисовки (если компилирую в msvc). segfault вызванный тем, что я пытаюсь вызвать метод объекта из вектора, при том что указатель ссылается на чистую область памяти (то есть объекта там уже нет) Разработку веду в clion (gcс + mingw) И периодами сверяюсь с msvc (там удобный профайлер, да и в целом компилятор по умолчанию более строгий). Понятно что весь код внутри update, я физически привести не смогу, вопрос вот в чем, может быть есть какие-то методики для понимания кто и в каком месте заменяет на heap'e реальные объекты таким образом, что указатель ведёт на чистую область памяти где не содержится изначально искомого объекта? Либо же я просто совершаю некую распространенную ошибку новичка и каким-то не правильным образом работаю с вектором таким образом что при наступлении определенных событий происходит segfault? Сразу оговорюсь, resize() у вектора я сам не вызываю, то есть аллокация новых элементов происходит автоматом и происходит успешно до какого-то момента. Так же я могу привести кусок кода на котором возникает (в случае неопределенных обстоятельств) segfault при gcc компиляции.
0
|
|||||||||||
| 21.11.2017, 12:27 | |
|
Ответы с готовыми решениями:
49
Как передать целочисленную матрицу типа std::vector<std::vector<int> > в функцию? Вывести значения std::vector<std::vector<int*> > |
|
309 / 221 / 74
Регистрация: 23.05.2011
Сообщений: 981
|
||||||
| 21.11.2017, 17:15 | ||||||
![]() Окей, тогда попробуй переписать цикл:
0
|
||||||
|
1 / 1 / 0
Регистрация: 21.11.2017
Сообщений: 24
|
|
| 21.11.2017, 17:15 [ТС] | |
|
0
|
|
|
183 / 181 / 66
Регистрация: 15.02.2015
Сообщений: 515
|
|
| 21.11.2017, 17:25 | |
|
mrAndersen7, понимаю что глупо, но всё же, не изменяете-ли вы косвенно или напрямую вектор items из метода update?
0
|
|
|
1 / 1 / 0
Регистрация: 21.11.2017
Сообщений: 24
|
|||
| 21.11.2017, 17:37 [ТС] | |||
|
Добавлено через 1 минуту
0
|
|||
|
309 / 221 / 74
Регистрация: 23.05.2011
Сообщений: 981
|
|||||||
| 21.11.2017, 17:45 | |||||||
|
При добавлении элементов, итераторы вектора могут стать невалидными.
Вот пор push_back:
Рекомендую попробовать сделать так, как я писал выше, только чуть изменив:
А новые значения element в моём цикле тоже принимают эти "странные значения"?
0
|
|||||||
|
1 / 1 / 0
Регистрация: 21.11.2017
Сообщений: 24
|
|||||||
| 21.11.2017, 17:59 [ТС] | |||||||
Но вот сортировка может быть вызвана и в середине цикла итерации.
0
|
|||||||
|
309 / 221 / 74
Регистрация: 23.05.2011
Сообщений: 981
|
||||||
| 21.11.2017, 18:05 | ||||||
(Entity *&a, Entity *&b).Добавлено через 1 минуту И вызывай сортировку после цикла update Потому что это точно портит итераторы, да и мою идею с индексами тоже. И это очень неоптимально.
0
|
||||||
|
1 / 1 / 0
Регистрация: 21.11.2017
Сообщений: 24
|
||
| 21.11.2017, 18:07 [ТС] | ||
|
0
|
||
|
309 / 221 / 74
Регистрация: 23.05.2011
Сообщений: 981
|
|
| 21.11.2017, 18:09 | |
|
Пожалуй, залей куда-нибудь на github проект, тут уже так не разобраться.
0
|
|
|
1 / 1 / 0
Регистрация: 21.11.2017
Сообщений: 24
|
||
| 21.11.2017, 20:10 [ТС] | ||
|
https://pastebin.com/qsLpw41P - Менеджер сущностей
Добавлено через 1 час 48 минут
0
|
||
|
зомбяк
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
|
||||||
| 21.11.2017, 20:32 | ||||||
|
Ошибка в этом
*e, в которой указатель.Добавлено через 3 минуты Да, ошибся. e тут не итератор, а просто ссылка.
0
|
||||||
|
1 / 1 / 0
Регистрация: 21.11.2017
Сообщений: 24
|
||
| 21.11.2017, 20:36 [ТС] | ||
0
|
||
|
зомбяк
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
|
||||||
| 22.11.2017, 04:42 | ||||||
|
Возможно у Entity (и дочерних классов) не виртуальный деструктор, потому не доудаляются...
Добавлено через 3 часа 3 минуты И ещё добавить проверку на дублирование элементов при удалении
0
|
||||||
|
309 / 221 / 74
Регистрация: 23.05.2011
Сообщений: 981
|
|
| 22.11.2017, 09:36 | |
|
Скинь вообще весь проект для MS VS, попробую подебажить.
0
|
|
|
183 / 181 / 66
Регистрация: 15.02.2015
Сообщений: 515
|
|||
| 22.11.2017, 10:13 | |||
|
Тут, похоже что во время выполнения той или иной операции, будь она в цикле или в лямбде (касательно sort), текущий итератор (хоть его и не видно, но он есть) становится невалидный, а произойти это может если в одном или нескольких методах из: getDrawOrder, getWorldCoordinates или update - происходит изменение вектора items, например создаётся один или несколько объектов, которые в конструкторе себя добавляют в items. Как бы инвалидация итератора в "renge base for" цикле может быть только в результате каких-либо действий в теле этого цикла (исключая многопоточность).
0
|
|||
|
1 / 1 / 0
Регистрация: 21.11.2017
Сообщений: 24
|
|||||||||
| 22.11.2017, 11:55 [ТС] | |||||||||
0
|
|||||||||
|
зомбяк
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
|
|||||||
| 22.11.2017, 12:33 | |||||||
|
При тестировании с полуслучайным добавлением-удалением, если отключить всю работу с itemsByGroup, SEGFAULT вылетало из-за дублирования элементов в itemsToRemove, когда для адреса элемента, к которому уже применялось delete e , повторно проходит итератор. Но это не единственная остановка, иногда останавливалось на вот этом - Ntdll!DbgBreakPoint signal-received - остановка выполнения - и с чем это связано, не понимаю. После продолжения программа успешно выполнялась. Если нет уверенности, что в void remove(Entity *item) попадают валидные адреса, теоретически можно сделать так:
0
|
|||||||
|
183 / 181 / 66
Регистрация: 15.02.2015
Сообщений: 515
|
||
| 22.11.2017, 14:23 | ||
|
Добавлено через 5 минут Вот грубый пример того, как можно поймать sigsegv при невалидном итераторе: http://rextester.com/EYM23196 если в коде убрать один update() в main, то ошибки уже не будет.
0
|
||
|
зомбяк
1585 / 1219 / 345
Регистрация: 14.05.2017
Сообщений: 3,940
|
|||||||
| 22.11.2017, 15:08 | |||||||
aaa.size() и aaa[i] значения сохранят актуальность даже после реаллокации вектора aaa, в отличии от итераторов или ссылок в новой форме записи for. Хотя конечно будет проигрыш по производительности.
0
|
|||||||
|
1 / 1 / 0
Регистрация: 21.11.2017
Сообщений: 24
|
|||||||||||
| 22.11.2017, 15:52 [ТС] | |||||||||||
|
Закомментил сортировку в принципе, для теста. Проблема пропала как таковая. Сейчас попробую добавление элементов класть в очередь (новый вектор) и суммировать вектора в конце фрейма
Добавлено через 36 минут В общем ситуация такая. Было изначально 2 места где был segfault на update() и на сортировке. В том месте где был update - он возникал, потому что была инвалидация итератора, по причине добавления в вектор новых сущностей, она решилась таким образом (как было предложено выше и на предыдущей странице):
Проблема с segfault на сортировке не решилась, даже при том условии что происходит она только после всех операций update и итерации по вектору, таким вот образом:
Добавлено через 2 минуты UPD: Проблема с segfault на сортировке присутсвтует только при компиляции через mingw + gcc, при комплияции через MSVC - проблемы нет, перепроверил несколько раз
0
|
|||||||||||
| 22.11.2017, 15:52 | |
|
Как изменять размер std::vector<std::vector>? Std::vector<std::pair<std::vector<int>::iterator, std::vector<int>::iterator>
Реализация класса MyString. Стандартная библиотека, std::string, std::vector Передача функции указатель на элемент std::vector<std::string> Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |
|
Новые блоги и статьи
|
|||
|
Сезонность закисления почв
anaschu 04.07.2026
200 часов это все равно моловато. Есть ситуации, но нестандартные, когда смена происходит за 5 лет.
Но обычно это 50 лет и более.
Наверное, закисление почвы происходит сезонно в средней. . .
|
В чем ценность человеческого опыта в глобальном смысле?
kumehtar 03.07.2026
Возможно, ценность человека не в том, что он однажды достигает мудрости, а в том, что он становится носителем карты пути. Он знает не только истину, но и последовательность внутренних изменений,. . .
|
интеграция AnyLogic с самописным REST API и переход на Odoo
anaschu 03.07.2026
Успешная интеграция AnyLogic с самописным REST API и переход на промышленную Odoo WMS
Сегодня проделал огромный путь от простой симуляции физических процессов до построения полноценной. . .
|
Поиск всех путей на ориентированном графе. Linux
dcc0 02.07.2026
Переработка старого кода из моей статьи.
Через несколько переработок от PHP кода к C89 (надеюсь, 89).
Но довольно запутанно получилось. Код для Linux.
Но если убрать time и то, что с ним. . .
|
|
Сам себя обучал rest api
anaschu 02.07.2026
Педагогический лайфхак: Почему чистый REST API для ученика намного круче, чем готовые библиотеки
Когда мы отказались от капризного JAR-файла AnyLogic и переписали код на стандартный HttpClient,. . .
|
rest api anylogic - выполнение модели на своём русском сайте
anaschu 02.07.2026
Как подружиться с AnyLogic Cloud API, победить провайдеров и развернуться Java-бэкенд в Docker на бесплатном хостинге: Двухдневный лог борьбы
Всем привет! Хочу поделиться свежим (и довольно. . .
|
Где деньги лежат
kumehtar 02.07.2026
Это - японская подводная лодка I-52 (тип C2, кодовое имя Momi) вышла из Японии в марте 1944 года с миссией в оккупированную немцами Францию (Лорьян). Это была одна из «Янаги»-миссий по обмену. . .
|
Krabik для WoW 3.3.5a, многоязычный
AmbA 02.07.2026
Допилил бота, думаю что окончательно. Изменения:
- добавлена многоязычность
- добавлено снятие скриншотов
- добавлено поддержание бафов хождения по воде (для жреца, дк и шамана)
- и так, по. . .
|