我正在使用Visual C ++ 2008 SP1。我有一个在调试模式下编译的应用程序,但是在发布模式下链接到库。
我在启动应用程序时遇到了崩溃。为了缩小问题,我创建了一个包含2个项目的简单解决方案:
'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上(在发布模式下创建一个库),我正在使用 Multi Threaded(/ MT),在exec_using_lib_release中,我正在使用 Multi Threaded Debug( / MTD)。我认为这是实现它的预期方式,因为我希望在没有调试信息的情况下创建.lib。我在MSDN Runtime library阅读了该文档,这些是以静态方式链接CRT的设置。
我也没有“公共语言运行时支持”。
答案 0 :(得分:8)
你没有 使用相同的运行时用于发布和调试模块(但它有帮助),只要你遵循非常具体的规则:永远不要混合和匹配访问分配的内存使用每个运行时。
更简单地说,如果你在一个dll中有一个例程来分配一些内存并将它返回给调用者,那么调用者就不能释放它 - 你必须在原来的dll中创建一个释放内存的函数。这样你就可以避免运行时不匹配。
如果您认为Windows dll仅构建版本(除非您拥有Windows的调试版本),但是您从调试应用程序中使用它们,您将看到它的重要性。
您现在的问题是您正在使用静态库,不再有dll边界,并且使用C运行时的静态版本编译lib中的调用。如果你的exe使用动态dll版本的运行时,你会发现链接器正在使用那个,而不是你的静态库使用的那个......你会崩溃。
所以,你可以将你的lib重建为dll;或者你可以确保它们都使用相同的CRT库;或者你可以确保他们都使用相同类型的CRT - 即dll版本或静态版本,同时保持调试/发布差异。
至少,我认为这是你的问题 - 什么是'代码生成,运行时库'设置?
答案 1 :(得分:5)
对于早先人们提到的发布和调试问题的混合,这些问题在错误的运行时库试图解除分配之前不会出现。我认为你遇到的是VS 2008默认启用了迭代器调试,因此你的lib和你的exe指的是std :: vector的不同实现。您需要将_HAS_ITERATOR_DEBUGGING = 0添加到预处理器设置中。然后,您将开始针对不同的运行时遇到不同堆的问题。在过去,我们有不同的规则和政策来避免这种情况,但现在我们只依赖于一致的构建环境 - 不要混淆和匹配。
答案 2 :(得分:2)
这里的问题是调试将使用c运行时的调试版本,并且发行版将使用c运行时的发布版本,当您尝试跨dll边界访问内存时,它将处于错误的运行时和崩溃。它最好只使用调试版本(或发布)
答案 3 :(得分:0)
附加的库不应跨库边界共享CRT资源。对于C代码,动态分配的内存必须在边界的同一侧解除分配。 对于C ++代码,您可以在DLL中使用std命名空间,但是使用std命名空间的那些对象应该通过库边界传递。
请参阅this回答类似问题