2009-08-04 36 views
6

我正在使用Visual C++ 2008 SP1。我有一个以调试模式编译的应用程序,但在发布模式下与库相链接。在Visual Studio中调试发行版中的库和调试时崩溃中的exe文件

我在应用程序启动时发生崩溃。为了使问题更小,我创建了2个项目的简单解决方案:

  • lib_release(生成的.lib,在释放模式)
  • exec_using_lib_release(genereates一个。exe,在调试模式下)

的“lib_release”项目是很简单的有一个简单的类:

//Foo.h 
#include <vector> 
class Foo { 
    std::vector<int> v; 
    public: 
    void doSomething(); 
}; 
//Foo.cpp 
#include "Foo.h" 
void Foo::doSomething() {} 

的“exec_using_lib_release”项目是简单的是这样的:

//main.cpp 
#include "Foo.h" 
int main() { 
    Foo foo; 
    foo.doSomething(); 
    return 0; 
} 

它崩溃了,这是How do you build a debug .exe (MSVCRTD.lib) against a release built lib (MSVCRT.lib)?报告的同样的问题,但他的回答对我来说并不奏效。

我得到了相同的链接器警告,我尝试了相同的步骤,但都没有工作。有什么我失踪?

编辑:

在lib_release(创建在释放模式库),我使用多线程(/ MT),并在exec_using_lib_release,我使用多线程调试(/ MTd)。我认为这是实现它的预期方式,因为我希望创建.lib而不用调试信息。我在MSDN Runtime library处阅读文档,这些是静态连接CRT的设置。

我没有'Common Language Runtime Support'。

+0

这是确切的示例代码(foo.h中),或者是简单的,而不是你真正尝试过什么? – Timbo 2009-08-04 13:57:16

+0

@Timbo它几乎是一样的,只是Foo类有一个.cpp版本,它已经实现了doSomething()方法。 – 2009-08-04 14:38:51

+0

你是静态库的提供者,还是第三方? – KJAWolf 2009-08-04 20:02:04

回答

8

你不用于发布和调试模块相同的运行时间(但它可以帮助),只要你遵循非常具体的规则:不要混合,并匹配访问使用每个运行时分配的内存。

简单来说,如果你在一个dll中有一个例程来分配一些内存并将它返回给调用者,那么调用者不能释放它 - 你必须在原始dll中创建一个释放内存的函数。这样可以避免运行时不匹配。

如果您认为在Windows DLL是唯一一款内置版本(除非你有Windows的调试版本),但你从你的调试应用程序使用它们,你会看到这是如何的问题。现在

你的问题是,您使用的是静态库,没有DLL边界了,而且在lib呼叫正在使用C运行时的静态版本编译。如果你的exe使用运行时的动态dll版本,你会发现链接器正在使用那个,而不是你的静态库使用的那个......并且你会碰到崩溃。

所以,你可以重建你的lib作为一个dll;或者你可以确保它们都使用相同的CRT库;或者您可以确保它们都使用相同类型的CRT - 即dll版本或静态版本,同时保持调试/版本差异。

至少,我认为这是你的问题 - '代码生成,运行时库'设置是什么?

+0

是的,这是我的问题。但是,如何将释放它们的库的lib开发者编译为'release',以便使它们与在调试模式下运行的程序“可链接”?他们是否遵循你所说的这些“严格的规则”? – 2009-08-04 16:35:00

+0

你在我们的lib中使用静态或动态CRT?如果你希望它是完全可移植的,那么使用静态版本,因为所有的CRT调用都会被嵌入到lib中。或者使用发布CRT构建你的exe文件。我不确定有很多商业静态库,人们倾向于提供dll。 – gbjbaanb 2009-08-04 18:45:36

+0

遵循这些特定规则,在调试 - 释放模式下是否可能存在不同包装的问题? – TripleS 2015-12-31 06:09:34

2

这里的问题是调试将使用c运行时的调试版本,并且发布将使用c运行时的发布版本,并且当您尝试访问跨dll边界的内存时,它将处于错误运行状态时间和崩溃。所有的最好的方法只使用调试版本一起(或释放)

+1

的提供者,你在哪里看到任何动态分配? – 2009-08-21 14:41:05

5

对于早期人们提到的释放和调试问题的混合,这些问题直到错误的运行时库试图解除分配才显示出来。我认为你所遇到的是VS 2008默认启用了迭代器调试,所以你的lib和你的exe指的是std :: vector的不同实现。您需要将_HAS_ITERATOR_DEBUGGING = 0添加到预处理器设置中。然后,你将开始在不同的运行时间碰到不同堆的问题。过去我们有不同的规则和政策来避免这种情况,但现在我们只依靠一致的构建环境 - 不要混合搭配。

0

附加库不应该跨库边界共享CRT资源。对于C代码,动态分配的内存必须在边界的同一侧解除分配。 对于C++代码,您可以在DLL中使用std名称空间,但是使用std名称空间的对象应该通过库边界传递。

看到this回答类似的问题

相关问题