将多个C ++ .lib项目转换为.dll项目时,Lua崩溃了!

今天我试图让“编辑并继续”在我的解决方案中工作,看起来是这样的:

游戏引擎.lib <- 游戏.lib <- 编辑器.exe

                        <- 服务器.exe

                        <- 客户端.exe

这样很好。但现在我想把引擎和游戏.lib变成.dll,这样我就可以使用Visual Studio C++的“编辑并继续”功能了。

所以我在里面加了一堆"__declspec(dllexport)",等等,它可以运行!

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

引擎和游戏都使用Lua,它们都有自己的静态C++接口函数。

我不确定,但我认为.dll有点像没有main函数的.exe,它们每个人都有自己的内存。因此,例如Game.dll导致Lua分配一些内存,Engine.dll再导致Lua将其释放,砰!正确吗?

有什么解决办法吗?当然Engine.dll应该负责Lua,但Game.dll应该能够通过新的静态函数扩展接口。

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

祝你有愉快的一天,

Antoon

P.S.为什么我在Stackoverflow上没有对返回值的控制?

原文链接 https://stackoverflow.com/questions/3383932

点赞
stackoverflow用户2101267
stackoverflow用户2101267

为什么你认为你需要对 DLL 进行编辑并继续?就我所使用的情况而言,它在可执行文件上也完美地工作。你发现有什么特定的错误导致你无法使用它吗?

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

2010-08-01 22:16:05
stackoverflow用户407438
stackoverflow用户407438

也许只是我自己,但我认为你提供的信息有点少。由于你提到你的问题与模块边界之间的内存分配有关,我建议你阅读以下文章:

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

基本上,内存必须使用与分配时相同的分配器进行释放,也就是说,不要混合使用 new / free。这也意味着你不应该跨模块边界分配和释放内存,因为模块可能是使用不同设置编译的,例如,调试分配器可能不同于在发布版本中使用的分配器,或者由于使用了不同版本的运行时(不同的发布版本,不同的供应商等)也可能不同。

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

2010-08-01 22:21:36
stackoverflow用户14089
stackoverflow用户14089

我猜想是一个 DLL/EXE 分配了内存,而另一个尝试释放它却崩溃了。

解决方法是确保所有二进制文件都使用以下编译选项编译:

  • 调试多线程 DLL (/MDd) 用于调试版本
  • 发行多线程 DLL (/MD) 用于发布版本

当然,还要确保所有的 DLL/EXE 都使用相同的编译器和选项进行编译...

这是让在同一进程中的二进制文件(EXE 和 DLL)共享其内存分配器的唯一方法。

2010-08-01 22:26:42
stackoverflow用户68204
stackoverflow用户68204

你写道:

引擎和游戏都使用Lua,并且它们都有自己的静态C++接口函数。

这就让我想到一个可能性,那就是引擎和游戏各自都静态链接到一个Lua的副本上。

如果是这样的话,那么当一个被一个副本创建的Lua状态被传递给另一个副本时,你会看到预料之中的结果。主要表现为破坏了内存状态并破坏了分配器。根本原因在于值“nil”的实现取决于Lua引擎内部某个地址。在同一进程中链接的第二个引擎副本将有一个不同的地址作为其“nil”的概念。这种方式最终会导致疯狂。

当然,如果游戏和引擎使用同一个Lua解释器副本(比如同时使用LUA51.DLL),那么我就是在说废话。

2010-08-03 08:30:32