2015-12-02 71 views
3

比方說,我有一個主要的DLL,其中有一類這樣的:是的std :: type_index安全跨越的DLL

class Test 
{ 
public: 

    typedef std::unordered_map< std::type_index, int > Map; 

    template < typename T > void SetValue(int val) 
    { 
     SetValue(std::type_index(typeid(T)), val); 
    } 

    template < typename T > int GetValue() 
    { 
     return GetValue(std::type_index(typeid(T))); 
    } 

protected: 

    // Defined in .cpp file 
    void SetValue(const std::type_index & idx, int val) 
    { 
     m_Map[idx] = val; 
    } 

    // Defined in .cpp file 
    int GetValue(const std::type_index & idx) 
    { 
     Map::const_iterator itr = m_Map.find(idx); 

     if (itr != m_Map.cend()) 
     { 
      return itr->second; 
     } 

     return 0; 
    } 

private: 

    Map m_Map; 
}; 

而且我通過幾個DLL文件共享類的一個實例。而在DLL中的一個我這樣設置一些值:

template < typename T > struct Dummy 
{ 

}; 

void InitFunc(Test * t) 
{ 
    t->SetValue< Dummy<int> >(32); 
    t->SetValue< Dummy<char> >(10); 
    t->SetValue< Dummy<float> >(27); 
} 

而在另一個DLL我嘗試使用相同Dummy類型獲取這些值。我會得到相同的值還是0?

+1

您應該更關心在嘗試使用在一個DLL中創建的'Test'之一併傳遞給另一個DLL時是否發生崩潰。你所有的DLL必須使用相同的編譯器,相同的選項進行編譯,確保使用的堆是相同的(對於'unordered_map')等。 – PaulMcKenzie

+0

使用'std :: unordered_map'只是一個例子。看來我形成了一個錯誤的問題。我的問題是如果'std :: type_index'指向相同的索引。 'hash_code'值將是相同的。 –

+0

我的觀點是你甚至不能考慮任何東西,除非DLL的構建完全一樣。另外,它不一定是'unordered_map' - 如果你的'Test'類最終做了任何*內存管理,如果不使用相同的堆,DLL之間的'Test'的顯式或隱式使用是有問題的。 – PaulMcKenzie

回答

2

如果我正確理解了這個問題,那麼您違反了ODR - 一個定義規則。看起來像你的'虛擬'類型是在兩個不同的翻譯單元中獨立定義的,這是一個不可否認的:)。現在,這會將你帶入未定義的土地,在這裏任何事情都是可能的 - 你可以得到相同的值,不同的值或沒有值。

+0

這個回答是完全錯誤的。 ODR不會*適用於Dummy是的類模板。見http://en.cppreference.com/w/cpp/language/definition'只要每個定義出現在不同的翻譯單元中,程序中可以有多個定義,每個定義的類型如下:class type ,枚舉類型,具有外部鏈接內聯變量的內聯函數(自C++ 17以來),類模板,非靜態函數模板,類模板的靜態數據成員,類模板的成員函數,部分模板特化, [...]' –

2

這很大程度上取決於您對「安全」和您的部署環境的定義。

@ SergeyA的答案的論點的關鍵在於編譯器在每個編譯單元中生成std::type_info對象 - 然後在鏈接每個DLL時由鏈接器合併。

雖然std::type_info將具有由標準定義的接口,但實現(特別是存儲佈局)是可能在編譯器,編譯器版本和編譯器選項之間改變的實現細節。

此外從CppReference

的type_index類是圍繞一個std的包裝類:: TYPE_INFO對象,可以被用作關聯索引和無序關聯式容器。與TYPE_INFO對象的關係通過指針」

保持那麼現在,我們正在依靠指針一個幾個定義到每個DLL爲好。

想想你可能用std::type_index做的一些事情 - 結果很可能取決於上下文 - 很大程度上取決於它們的來源。

現在回到問題:這安全嗎?可能不是。作爲一般規則,你應該避免在DLL接口邊界上暴露幾乎所有的std庫(尤其是STL容器)。

如果你堅持這樣做,它永遠只能有工作的變化,這些非常有限的情況下:

  • 所有組件都建有完全相同的編譯器
  • 所有組件都具有精確建相同的編譯器選項(調試VS發行一直是一個巨大的問題,在Windows上)
  • 所有組件都部署在一起作爲一個單元
  • 組件沒有暴露給別人
  • 的API

這實際上對於大量的商業軟件來說是真實的,你會發現它比你想象的要多,但我不會推薦它。