2010-08-01 81 views
1

今天,我试图让编辑&继续在我的解决方案,它看起来像这样的工作:多个C++ .lib项目到.dll项目,Lua崩溃!

游戏引擎的.lib < - 游戏的.lib < - 编者.EXE

     <- Server .exe 

         <- Client .exe 

其中一期工程很好。但是现在我想将引擎和游戏.libs转换为.dll文件,因此我可以使用Visual Studio C++的继续编辑功能。

因此,我得到了一堆“__declspec(dllexport)”在那里等工程就好,它运行!

但在某些情况下,它崩溃。实际上,它总是在与释放内存相关的Lua函数中崩溃。

引擎和游戏都与Lua一起工作,它们都有自己的静态C++接口函数。

我不确定,但我想.dll有点像没有主函数的.exe,每个都有自己的内存。因此,当例如Game.dll导致Lua分配一些内存,并且Engine.dll导致Lua再次释放它时,繁荣!正确?

关于如何解决这个问题的任何想法?当然Engine.dll应该负责Lua,但是Game.dll应该能够用新的静态函数来扩展接口。

编辑:没有更多的崩溃后,我把Lua本身变成一个.dll。在我尝试这个之前,我还使用与所有其他项目相同的编译器重新编译了静态,并且我重复检查了运行时库,并且它们都是相同的,并且我正在链接到正确的调试/版本库。我仍然很好奇这里发生了什么。

有一个愉快的一天,

安东

附:为什么我无法控制Stackoverflow的回报?

回答

3

您写道:

的引擎和游戏的Lua都工作,他们都有自己的静态C++接口功能。

这表明,我认为引擎和游戏中的每个单独静态链接到Lua副本的可能性。

如果这是真的,那么这正是如果一个副本创建的Lua状态被传递给另一个副本时,您会发生的。典型的结果是弄乱了内存状态并破坏了分配器。根本原因在于值nil的实现取决于Lua引擎内部的地址。链接到同一进程的引擎的第二个副本将具有不同的地址作为其概念nil。这种方式最终导致疯狂。

当然,如果游戏和引擎共享Lua解释器的单个副本(通过两个都使用LUA51.DLL),然后我吠叫错误的树。

+0

这是答案,谢谢先生!是的,我静态链接到Engine.dll和Game.dll,因为最初Engine.lib会链接它,而Game.lib会自动继承这些符号。 是的,把Lua变成一个dll来修复它。 非常有趣的bug =)。 – Xilliah 2010-08-03 12:59:09

0

为什么你认为你需要DLL编辑并继续?就我所使用的来说,它对于可执行文件也很好。是否有一些特定的错误让你无法使用它?

DLLs不会获得自己的内存段,但它们可能会使用自己的可能不兼容的分配机制。请确保所有DLL和主程序都与相同版本的C运行时库链接(调试或发布,多线程或非多线程,以及相同的版本号)。

+0

编辑和继续不支持静态库在Visual Studio C++ – Xilliah 2010-08-01 22:41:58

+0

谢谢,我错过了静态库部分。我通常不会自己与他们一起工作。 – 2010-08-01 22:46:49

1

也许这只是我,但我觉得你包括的信息有点稀疏。既然你提到了你的问题,虽然涉及到跨模块边界的内存分配,我建议下面的文章给你:

http://blogs.msdn.com/b/oldnewthing/archive/2006/09/15/755966.aspx

基本上,内存必须使用用于分配相同的分配被释放它,即不混合新/免费 - 但它也意味着你不应该跨越模块边界分配和释放内存,因为模块可能被编译为不同的设置,例如,调试分配器可能不同于发布版本,或者由于使用不同的运行时版本(不同版本,不同的供应商等),它可能会有所不同。)

大多数情况下,通过提供项目中每个其他模块使用的一致接口来处理单个模块中的内存分配是最安全的。

+0

有趣,因为我确信Lua是分配和释放记忆的人。运行时库全部设置为相同,包括Lua在内的所有项目都使用相同的编译器进行编译。也许有一两个选择是不同的。我总是很难比较VS中的编译器选项。 – Xilliah 2010-08-01 22:43:12

0

我想一个DLL/EXE分配内存,另一个尝试释放它,并崩溃。

的解决方案是确保所有的二进制文件中都安装编译:

  • 调试多线程DLL(/ MDD)的调试版本发布
  • 发布多线程DLL(/ MD)建立

当然,确保所有的DLL/EXE文件用相同的编译器和编译选项...

这是二进制文件的唯一途径(EXE和DLL )在同一个进程中共享它们的内存分配器。