多个 C++ .lib 项目到 .dll 项目,Lua 崩溃!

Posted

技术标签:

【中文标题】多个 C++ .lib 项目到 .dll 项目,Lua 崩溃!【英文标题】:Multiple C++ .lib projects to .dll projects, Lua crashes! 【发布时间】:2010-08-01 22:07:48 【问题描述】:

今天我尝试让 Edit & Continue 在我的解决方案中工作,如下所示:

游戏引擎.lib

                        <- Server .exe

                        <- Client .exe

效果很好。但是现在我想把引擎和游戏的 .libs 变成 .dlls,这样我就可以使用 Visual Studio C++ 的 Edit & Continue 功能了。

所以我在那里得到了一堆“__declspec(dllexport)”,等等。工作得很好,它运行了!

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

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

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

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

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

祝你有美好的一天,

安东

附:为什么我无法控制 *** 的退货?

【问题讨论】:

【参考方案1】:

你写道:

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

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

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

当然,如果游戏和引擎共享 Lua 解释器的一个副本(比如说两者都使用 LUA51.DLL),那么我就找错了树。

【讨论】:

这就是答案,谢谢先生!是的,我确实将它静态链接到 Engine.dll 和 Game.dll,因为原本 Engine.lib 会链接它,而 Game.lib 当然会自动继承符号。是的,将 Lua 变成 dll 修复了它。非常有趣的错误 =)。【参考方案2】:

也许只有我一个人,但我发现您提供的信息有点稀疏。既然您提到您的问题与跨模块边界的内存分配有关,我会向您推荐以下文章:

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

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

大多数时候,通过提供项目中所有其他模块都使用的一致接口,只在单个模块中处理内存分配是最安全的。

【讨论】:

很有趣,因为我确信 Lua 是分配和释放内存的那个。并且运行时库都设置为相同,包括 Lua 在内的所有项目都使用相同的编译器进行编译。也许一两个选项是不同的。我总是觉得很难比较 VS 中的编译器选项。【参考方案3】:

为什么你认为你需要一个 DLL 编辑并继续?就我使用它而言,它在可执行文件上也能很好地工作。您是否遇到了一些阻止您使用它的特定错误?

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

【讨论】:

Visual Studio C++ 下的静态库不支持编辑并继续 谢谢,我错过了静态库部分。我自己通常不会和他们一起工作。【参考方案4】:

我猜是一个 DLL/EXE 分配了内存,另一个试图释放它,然后崩溃了。

解决方案是确保您的所有二进制文件都使用以下任一方式编译:

为调试构建调试多线程 DLL (/MDd) 为发布版本发布多线程 DLL (/MD)

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

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

【讨论】:

以上是关于多个 C++ .lib 项目到 .dll 项目,Lua 崩溃!的主要内容,如果未能解决你的问题,请参考以下文章

一个C++项目, 已有一些静态库(.lib)和所有的函数声明(.h),怎么生成一个动态库(dll)

Qt C++:包含项目文件夹中的所有库文件

C++ 可执行文件是不是包括 .obj、.lib 和 .dll?

无法链接 GLFW C++;添加了 .dll、.h、.lib,但仍然获得 LNK2019

为啥类库 (dll) 也不生成 lib 文件?

如何将 .dll 库与 C++ VS 项目链接?