0

在我阅读问题之前,我没有意识到在 .dll 库中依赖于编译时发生的事情的对象类型可能会出现问题,在这种情况下我可以忽略 C4251 警告吗?实际上,如果库的库编译设置和使用该库的程序不同,可能会出现一些错误。这是一个例子:

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文件

#include "dll.h"
#include <iostream>
using namespace std;

int main(void)
{
  HelloWorld myworld;

  return 0;
}

如果我编译 dll.h 和 dll.cpp 以使用 DTEST 的定义创建 dll.lib 和 dll.dll,但编译 exe.cpp 而不使用 DTEST 的定义。我将遇到运行时检查失败 #2 错误。有人可以解释为什么我有这个错误。谢谢!

4

2 回答 2

2

您有此错误是因为DTEST它是一个预处理器宏,并且您没有为程序的所有部分一致地定义它。当您的代码到达实际编译器时,它已被完全删除,因此编译器不会发现问题。如果你定义DTEST了 fordll.cpp而不是 for 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有两种不同的想法HelloWorlddll.cpp认为它包含test,但exe.cpp认为它不包含。有一个运行时检查可以捕获这种不匹配,这就是您所看到的。

于 2013-05-03T17:05:54.230 回答
1

编译器看到的是预处理器扩展的结果。在您的示例中,编译器看到:

class HelloWorld
{
public:
    int test;
    HelloWorld();
};

dll.cpp, 和

class HelloWorld
{
public:
    HelloWorld();
};

exe.cpp. 同一类,两种不同的定义。这违反了单一定义规则,导致未定义的行为。

这与 C4251 警告无关(如果我理解正确,它只涉及不同 DLL 之间的链接)。

于 2013-05-03T17:01:11.060 回答