2013-05-03 93 views
0

我沒有意識到.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錯誤。有人可以解釋爲什麼我有這個錯誤。謝謝!

+2

您是否期望您的程序運行?你會如何證明它? – 2013-05-03 16:49:00

回答

2

你有這個錯誤,因爲DTEST是一個預處理器的宏,你沒有爲你的程序的所有部分一致地定義它。當代碼到達實際編譯器時,它會被完全刪除,所以編譯器不會發現問題。如果你定義DTESTdll.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.cppexe.cppHelloWorld有兩個不同的想法:dll.cpp認爲它包含test,但exe.cpp認爲它不是。有一個運行時檢查,捕捉這種不匹配,這是你所看到的。

1

編譯器看到的是預處理器擴展的結果。 在您的例子,編譯器看到:

class HelloWorld 
{ 
public: 
    int test; 
    HelloWorld(); 
}; 
dll.cpp

,並

class HelloWorld 
{ 
public: 
    HelloWorld(); 
}; 
exe.cpp

。同一類,兩個不同的定義。這是 違反了一個定義規則,導致 未定義的行爲。

這與C4251警告無關(如果我正確理解 ,只關心不同的 DLL之間的鏈接)。

相關問題