D/DMD:退出程序会导致错误(SEGFULT、sigabort等)

D/DMD:退出程序会导致错误(SEGFULT、sigabort等),d,dmd,D,Dmd,我有空闲时间的游戏项目,用D、SDL2和OpenGL(被遗弃)编写,共享的部分组成了某种引擎。要点: Linux Mint 17.2 DMD 2.069.0-b2(也使用其他最新版本,如2.067.1) SDL2 2.0.2(来自存储库) 没有线(只有纤维) 可在此处访问整个源代码: 症状:退出-使用exit()退出和从main()返回-几乎总是导致glibc抛出各种信号或segfault,如: *** Error ...: munmap_chunk(): invalid pointer:

我有空闲时间的游戏项目,用D、SDL2和OpenGL(被遗弃)编写,共享的部分组成了某种引擎。要点:

  • Linux Mint 17.2
  • DMD 2.069.0-b2(也使用其他最新版本,如2.067.1)
  • SDL2 2.0.2(来自存储库)
  • 没有线(只有纤维)
可在此处访问整个源代码:

症状:退出-使用exit()退出和从main()返回-几乎总是导致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
*** core.exception.InvalidMemoryOperationError@src/core/exception.d(679): ...
**** Segmentation fault
做一些小的改变——比如在帧缓冲区类中添加析构函数或者其他任何东西——可以改变行为,即使这样,这也不会发生在我所有的游戏草图中。目前,它发生在“projects/cylinderium”中,但不会发生在“demo/objectview”或“testbench/wolfish”等项目中

我一直怀疑这是由SDL2库对象(如SDL_Surface)引起的,因为这些对象是在D运行时之外分配的,但我还没有找到这一点。我的另一个疑点是,有来自对象析构函数的调用,例如,deralict,并且已经被析构函数破坏了

基本上,在关机时出错并不危险,因为退出将清除一切。但在知道原因之前,我担心这是一个更严重错误的症状,当我有更复杂的游戏时(例如,在加载新游戏关卡期间,或长时间运行游戏时),错误会爆发

问题:

1) DMD运行时调用析构函数的顺序是什么?在调用使用OpenGL函数(例如glDeleteTextures)创建的所有对象的析构函数之前,是否会导致(例如)废弃的OpenGL接口被析构函数破坏

2) 我已经钩住了我自己类中的大多数析构函数,但是我能钩住每个析构函数来跟踪DMD在运行时关闭时删除的内容和顺序吗

3) 如果您碰巧能够成功地获取、编译和运行项目,我将很高兴听到您是否能够重现错误


我现在有点不知所措,如果有什么好主意,我将不胜感激。

我想我已经找到了原因

为完整起见,在静态构造函数中初始化SDL(SDL_Init,TTF_Init,…)的模块已使用静态析构函数关闭它们(SDL_Quit,…)。另一方面,我在分配了SDL的析构函数中分别删除了SDL分配的资源。这些是在运行时释放资源所必需的

我之前已经与析构函数一起努力释放SDL_Font*和SDL_Surface*,因此我添加了全局SDL_up标志,以防止在SDL关闭后调用

我忘记的是,我还管理SDL资源。。。更多的调试显示模块析构函数确实是在操纵杆析构函数之前调用的,调用SDL释放资源导致了错误


修复:我从模块析构函数中删除了SDL/TTF/IMG Quit调用和SDL_up标志。这已经是我第二次因为同样的原因花费数小时了,我决定最好不要让资源分配变得更复杂,而是放弃正统的完整Init-Quit调用对(并让系统退出以摆脱SDL)。

我想我已经找到了原因

为完整起见,在静态构造函数中初始化SDL(SDL_Init,TTF_Init,…)的模块已使用静态析构函数关闭它们(SDL_Quit,…)。另一方面,我在分配了SDL的析构函数中分别删除了SDL分配的资源。这些是在运行时释放资源所必需的

我之前已经与析构函数一起努力释放SDL_Font*和SDL_Surface*,因此我添加了全局SDL_up标志,以防止在SDL关闭后调用

我忘记的是,我还管理SDL资源。。。更多的调试显示模块析构函数确实是在操纵杆析构函数之前调用的,调用SDL释放资源导致了错误


修复:我从模块析构函数中删除了SDL/TTF/IMG Quit调用和SDL_up标志。出于同样的原因,这已经是我第二次花费数小时,我决定最好不要让资源分配变得更复杂,而是放弃正统的complete Init Quit调用对(并让系统退出以摆脱SDL)。

析构函数是按未定义的顺序调用的。有时,子对象的析构函数在其父对象之前被调用,因为GC认为整个对象树同时消亡。无效内存错误通常意味着您试图引用析构函数中未手动管理的内容。谢谢!是的,我已经怀疑析构函数是按随机顺序调用的,经过几个小时的调试,我想我找到了原因。我马上发布我的发现。析构函数是按未定义的顺序调用的。有时,子对象的析构函数在其父对象之前被调用,因为GC认为整个对象树同时消亡。无效内存错误通常意味着您试图引用析构函数中未手动管理的内容。谢谢!是的,我已经怀疑析构函数是按随机顺序调用的,经过几个小时的调试,我想我找到了原因。我马上就发布我的发现。