【发布时间】:2015-10-21 20:14:14
【问题描述】:
我有空闲时间的游戏项目,用 D、SDL2 和 OpenGL(废弃)编写,共享部分形成引擎。要点:
- Linux Mint 17.2
- DMD 2.069.0-b2(也使用其他最新版本,例如 2.067.1)
- SDL2 2.0.2(来自存储库)
- 没有线(只有纤维)
完整的源代码可以在这里访问:https://github.com/mkoskim/games
症状: 退出 - 使用 exit() 退出和从 main() 返回 - 几乎总是导致 glibc 抛出各种信号或段错误,例如:
*** Error ...: munmap_chunk(): invalid pointer: ... *** ... Aborted
*** Error ...: double free or corruption (out): ... *** ... Aborted
*** Error ...: free(): invalid pointer: ... *** ... Aborted
*** Error ...: corrupted double-linked list: ... *** ... Aborted
*** core.exception.InvalidMemoryOperationError@src/core/exception.d(679): ...
**** Segmentation fault
做一些小的改变——比如向 Framebuffer 类或任何东西添加析构函数——可以改变行为,即使这样,这也不会发生在我拥有的每个游戏草图中。目前它发生在“projects/cylinderium”中,但不会发生在“demo/objectview”或“testbench/wolfish”等项目中。
我一直怀疑它是由 SDL2 库对象(如 SDL_Surface)引起的,因为它们是在 D 运行时之外分配的,但我还没有设法找到这个。我的另一个怀疑是,从对象析构函数调用例如废弃的,并且已经被销毁了。
基本上在关机时出错并不危险,因为退出无论如何都会清除所有内容。但在知道原因之前,我担心这是更严重错误的症状,当我有更复杂的游戏时(例如在加载新游戏关卡或长时间运行游戏时),它会爆炸。
问题:
1) DMD 运行时调用析构函数的顺序是什么?它会导致例如在调用所有使用 OpenGL 函数(例如 glDeleteTextures)创建的对象的析构函数之前销毁废弃的 OpenGL 接口?
2) 我已经在自己的类中挂钩了大多数析构函数,但我可以挂钩每个析构函数以跟踪 DMD 在运行时关闭时删除的内容和删除顺序吗?
3) 如果您碰巧能够成功获取、编译和运行项目,我很高兴听到您能否重现该错误。
我现在有点没有想法,任何可以在哪里寻找的想法都会受到赞赏。
【问题讨论】:
-
析构函数以未定义的顺序调用。有时,子对象的析构函数在其父对象之前被调用,因为 GC 认为整个对象树同时死亡。无效的内存错误通常意味着您尝试在析构函数中引用您未手动管理的内容。
-
谢谢!是的,我已经怀疑析构函数是按随机顺序调用的,经过数小时的调试,我想我找到了原因。我稍后会发布我的发现。