2012-12-30 68 views
2

我正在使用VS2010和VS2012的項目解決方案。Visual Studio 2010和2012中STL容器的字節大小差異

VS2010項目調用VS2012中的函數,反之亦然。這一開始工作得很好,但是當我還需要在兩個項目之間共享變量時,我注意到變量似乎沒有相同的內存對齊方式,並且每個項目都以不同的方式解釋相同的內存地址。

更新: 似乎只使用STL的容器,不包含的std ::工作正常,其他結構和類時發生。

爲了說明問題,在不同的Visual Studio版本上運行時,下面的代碼應該會得到不同的結果。

#include <string> 
#include <vector> 

int main() 
{ 
    int stringSize = sizeof(std::string);   // Yelds 32 on VS2010, 28 on VS2012 
    int intVectorSize = sizeof(std::vector<int>); // Yelds 20 on VS2010, 16 on VS2012 

    return 0; 
}; 

更新這兩個項目相同的版本不可能我還沒有,因爲我有幾個依賴綁一個版本。

有沒有人知道解決方案或繞過問題的方法?

我會盡快升級項目都在VS2012編譯器,因爲它是可能的,但現在我跳了快速和骯髒的解決方案所以我纔可以工作相處。由於它似乎只發生在STL容器中,所以有可能在所有項目上使用舊版本的庫?或者是否有可能愚弄編譯器?也許改變填充大小?

此外,在一個std :: vector的第一元素似乎讀得很好,只有在矢量隨後元素似乎得到。 (見圖片。)在 「main.cpp中」 調試 「擷取的」 變量

Debug Image

圖片在2010年和2012年編制


有人要我澄清變量被分享的方式。

我們正在編譯第一個項目到VS2012編譯模式的DLL中,然後嘗試訪問VS2010中的那個。

下面是重新創建問題的一些代碼。如果您想自己嘗試,可以下載完整的VS2012解決方案here

此代碼使用VS2012編譯爲DLL。

DllExport.h

#ifdef DLLHELL_EX 
#define DLL_API __declspec(dllexport) 
#else 
#define DLL_API __declspec(dllimport) 
#endif 

#include <vector> 
#include <string> 

class DLL_API Foo 
{ 
public: 
    Foo(); 
    ~Foo(); 

    std::vector<std::string>* exposedMember; 
}; 

DLLEXPORT。CPP

#include "DllExport.h" 

Foo::Foo() 
{ 
    // Create member 
    exposedMember = new std::vector<std::string>(); 

    // Fill member with juicy data 
    for(int i=0; i<5; i++) 
      exposedMember->push_back("Fishstick"); 
} 

Foo::~Foo() 
{ 
    // Clean up behind ourselves like good lil' programmers 
    delete exposedMember; 
} 

此代碼使用DLL和使用VS2010被編譯。

的main.cpp

#include "DllExport.h" 

int main() 
{ 
    // Creating class from DLL 
    Foo bar; 

    // Fetching "exposedMember" from class 
    std::vector<std::string>* member = bar.exposedMember; 

    return 0; 
} 

該DLL的創建,使用this教程

+0

你知道爲什麼會發生? – elyashiv

+2

似乎合理的是,更新版本的STL將以不同的方式/更高效地實現各種功能。如果您將VS2012指向VS2010的include/lib文件夾,會發生什麼? – DCoder

+6

通過「共享兩個項目之間的變量」,你會發現什麼?這是二進制序列化?使用文字。它是共享內存嗎?別。它是DLL嗎?使用標準的DLL類型(OLE自動化類型)。 –

回答

-2

因爲我沒有不使用不同版本的選項,最接近於解決我認爲這個問題是通過使用指針STL的容器而不是直接訪問(例如的,而不是std::vector<std::string*>*std::vector<std::string>*)他們。

如果可能的話,我仍然非常喜歡非指針解決方案,但至少這樣我就不必發明我自己的字符串和矢量類作爲解決方法。

Pointers inside visual studio


更新

人顯然並不很喜歡這個答案。就我個人而言,我認爲最好被告知有一個解決方案,而不是被告知不應該做任何事情。該解決方案拯救了我們,因爲它使我們能夠繼續工作,直到幾周後我們可以將所有內容升級到同一編譯器。

雖然,批評有一些優點。解決方案儘管可能非常危險,但在單獨分配而不是結構的一部分時,String類的佈局在兩個編譯器中都是相同的。

更好的解決方案很可能僅僅是:

使用C型代替,例如請使用.c_str()來暴露C字符串,而不是直接從DLL訪問字符串的 ,或者用C字符串替換所有的 字符串。

我現在認爲這是@CoryNelson與most people choose to export only C types的意思,但由於我當時的無知和缺乏經驗與C-類型,我不明白這一點,我想我只是被告知這是不可能,我很愚蠢的嘗試。

同樣對於投票的人來說,如果你提供瞭解釋爲什麼,而不是我自己猜測,將不勝感激。只要有理由,我對批評沒有任何問題。

+0

我接受了我自己的答案,因爲它允許我繼續我的工作。希望我能儘快將所有內容升級到VS2012,以避免將來出現令人討厭的驚喜,但同時一切似乎都奏效。 – Adelost

+0

它很可能被低估,因爲通過指針訪問某些東西並不能解決問題。實現仍然可以瘋狂地改變。最好的解決方案是僅在您的控制下傳遞C類型,即「char const **」而不是「vector 」。 –

10

你絕對不應該從不同的版本運行的混合類型。即使它們的大小相同,它們也可能將變量存儲在不同的位置,或者某些算法可能會稍微改變。即使類型完全相同,不同的編譯器可能會選擇以不同的方式表示它們。

確實沒有好辦法做到這一點。 C++不保證其標準庫的實現不會改變,即使編譯器沒有這樣做,編譯器似乎也不會同意ABI(即使在相同編譯器的版本之間)。當爲他人編寫消費API時,大多數人選擇只導出完全在他們控制之下的C類型。

+1

+1 - 我還會補充說,這些類型的大小在調試版本和發佈版本之間也會有所不同,這樣混合這些組件就會出現問題。 – Bukes

+0

這聽起來太糟糕了。我打算儘快將這兩個項目升級到VS2012編譯器,但現在我無法讓Qt libraries 5.0.0在VS2012下工作。只要我不試圖訪問包含std-stuff的類,它似乎工作正常,所以這就是爲什麼我跳到那裏有一些快速和骯髒的修復,所以我只是可以相處的同時工作。 – Adelost

+2

_C++ _不是一個不穩定的語言。它缺少一個標準_ABI_,也許這就是你的意思? –

相關問題