0

I did not realize in a .dll library object types that depends on things that happen at compile time can case problems until I read the question Could I ignore C4251 warning in this case? In deed, if the library compilation settings for the library and the program that uses the library are different, some errors can occur. Here is an example:

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;
}

If I compile dll.h and dll.cpp to create dll.lib and dll.dll with the definition of DTEST but compile exe.cpp without the definition of DTEST. I will have a runtime check failure #2 error. Could some explain why I have this error. Thanks!

Community
  • 1
  • 1
feelfree
  • 11,175
  • 20
  • 96
  • 167

2 Answers2

2

You have this error because DTEST is a preprocessor macro and you are not defining it consistently for all pieces of your program. It is completely removed by the time your code reaches the actual compiler, so the compiler won't catch the problem. If you define DTEST for dll.cpp but not for exe.cpp, then exe.cpp will look like this to the compiler:

(...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;
}

However, dll.cpp will look like this:

(...contents of <iostream>...)
(...contents of <string>...)

using namespace std;

class __declspec(dllexport) HelloWorld
{
public:
  int test;
  HelloWorld();

};

HelloWorld::HelloWorld()
{
    test=0;
}

The problem here is dll.cpp and exe.cpp have two different ideas of what HelloWorld is: dll.cpp thinks it contains test, but exe.cpp thinks it doesn't. There is a runtime check that catches this mismatch, which is what you're seeing.

Richard Walters
  • 1,464
  • 8
  • 16
1

What the compiler sees is the results of preprocessor expansion. In your example, the compiler sees:

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

in dll.cpp, and

class HelloWorld
{
public:
    HelloWorld();
};

in exe.cpp. Same class, two different definitions. That's a violation of the one definition rule, which results in undefined behavior.

This has nothing to do with the C4251 warning (which if I understand correctly, only concerns linking between different DLLs).

James Kanze
  • 150,581
  • 18
  • 184
  • 329