У меня есть бесплатные игровые проекты, написанные с D, SDL2 и OpenGL (заброшенные), разделяемые части, образующие сортировку двигателя. Ключевые моменты:D/DMD: Выход из программы вызывает ошибки (segfault, sigabort, ...)
- Linux Mint 17.2
- DMD 2.069.0-b2 (и другие последние версии используются, например, 2.067.1)
- SDL2 2.0.2 (из репозитория)
- Нет нитей (только волокна)
весь источник можно получить здесь: https://github.com/mkoskim/games
Симптом: Выхода - как quit'ing с выходом() и возвращение из основных() - вызывает почти всегда GLibC бросать различные сигналы или Segfault, как:
*** Error ...: munmap_chunk(): invalid pointer: ... *** ... Aborted
*** Error ...: double free or corruption (out): ... *** ... Aborted
*** Error ...: free(): invalid pointer: ... *** ... Aborted
*** Error ...: corrupted double-linked list: ... *** ... Aborted
*** [email protected]/core/exception.d(679): ...
**** Segmentation fault
внесения небольших изменения - как добавление деструктора класса FrameBuffer или что-нибудь - может изменить поведение, и даже тогда этого не происходит в каждой игре, которую я имею. На данный момент это происходит в «проектах/цилиндрах», но не происходит в таких проектах, как «demo/objectview» или «testbench/wolfish».
Я давно подозреваю, что это вызвано объектами библиотеки SDL2 (например, SDL_Surface), поскольку они выделены вне времени выполнения D, но мне еще не удалось отследить это. Другой подозреваемый, который у меня есть, - это то, что происходят вызовы от деструктора объекта, например. заброшенным, и это уже разрушено.
В принципе, ошибки при выключении не опасны, так как выход все равно очистит все. Но, зная причину, я беспокоюсь, что это признак более серьезной ошибки, которая затем взорвется, когда у меня будет более сложная игра (например, во время загрузки нового игрового уровня или продолжения игры в течение длительного времени).
Вопросы:
1) В каком порядке DMD выполнения вызовов деструкторов? Может ли это вызвать, например, Вызывающий интерфейс OpenGL, который должен быть разрушен до того, как вызываются деструкторы всех созданных объектов с использованием функций OpenGL (например, glDeleteTextures)?
2) Я уже подключил большинство деструкторов в своих классах, но могу ли я подключить каждый деструктор для отслеживания того, что и в каком порядке DMD удаляется при завершении работы?
3) Если вам удастся успешно получить, скомпилировать и запустить проекты, я был бы рад услышать, если вы можете воспроизвести ошибку.
В настоящее время я немного из идей, любые идеи, на которые нужно смотреть, будут оценены.
Деструкторы вызываются в неопределенном порядке. Иногда деструкторы для дочерних объектов вызывается перед их родительскими объектами, потому что GC считает, что все дерево объектов умирает одновременно. Недопустимая ошибка памяти обычно означает, что вы пытались ссылаться на что-то в деструкторе, которого вы не управляете вручную. –
Спасибо! Да, я уже подозревал, что деструкторы вызываются в случайном порядке, и после нескольких часов отладки я думаю, что нашел причину. Я выложу свои выводы в одно мгновение. – MaKo