2012-12-30 37 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_,也许这就是你的意思? –

相关问题