为什么我会有运行时检查失败错误?
问题描述:
我没有意识到.dll库中的对象类型依赖于编译时发生的事情可能会遇到问题,直到我看到问题Could I ignore C4251 warning in this case?事实上,如果库的编译设置和使用库的程序是不同的,可能会发生一些错误。这里有一个例子:为什么我会有运行时检查失败错误?
dll.h
#include <iostream>
#include <string>
using namespace std;
class __declspec(dllexport) HelloWorld
{
public:
#ifdef DTEST
int test;
#endif
HelloWorld();
};
dll.cpp
#include "dll.h"
HelloWorld::HelloWorld()
{
#ifdef DTEST
test=0;
#endif
}
exe.cpp
#include "dll.h"
#include <iostream>
using namespace std;
int main(void)
{
HelloWorld myworld;
return 0;
}
如果我编译dll.h和dll.cpp到用DTEST的定义创建dll.lib和dll.dll,但不用DTEST的定义编译exe.cpp。我将有一个运行时检查失败#2错误。有人可以解释为什么我有这个错误。谢谢!
答
你有这个错误,因为DTEST
是一个预处理器的宏,你没有为你的程序的所有部分一致地定义它。当代码到达实际编译器时,它会被完全删除,所以编译器不会发现问题。如果你定义DTEST
为dll.cpp
而不是exe.cpp
,然后exe.cpp
看起来像这样的编译器:
(...contents of <iostream>...)
(...contents of <string>...)
using namespace std;
class __declspec(dllexport) HelloWorld
{
public:
HelloWorld();
};
(...contents of <iostream> again...)
using namespace std;
int main(void)
{
HelloWorld myworld;
return 0;
}
然而,dll.cpp
看起来就像这样:
(...contents of <iostream>...)
(...contents of <string>...)
using namespace std;
class __declspec(dllexport) HelloWorld
{
public:
int test;
HelloWorld();
};
HelloWorld::HelloWorld()
{
test=0;
}
这里的问题是dll.cpp
和exe.cpp
HelloWorld
有两个不同的想法:dll.cpp
认为它包含test
,但exe.cpp
认为它不是。有一个运行时检查,捕捉这种不匹配,这是你所看到的。
答
编译器看到的是预处理器扩展的结果。 在您的例子,编译器看到:
class HelloWorld
{
public:
int test;
HelloWorld();
};
在
dll.cpp
,并
class HelloWorld
{
public:
HelloWorld();
};
在
exe.cpp
。同一类,两个不同的定义。这是 违反了一个定义规则,导致 未定义的行为。
这与C4251警告无关(如果我正确理解 ,只关心不同的 DLL之间的链接)。
您是否期望您的程序运行?你会如何证明它? – 2013-05-03 16:49:00