我正在开发VS2010和VS2012项目的解决方案。
VS2010项目调用VS2012中的函数,反之亦然。这开始工作得很好,但是当我还需要在两个项目之间共享变量时,我注意到变量似乎没有相同的内存对齐,并且每个项目都以不同的方式解释相同的内存地址。
更新: 它只在使用 STL-containers 时才出现,其他不包含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中的第一个元素看起来很好,只有后续元素才能获得加扰 。 (见图。)
在2010年和2012年编制的“main.cpp”中调试“Fetched”变量的图片。
有人希望我澄清变量的共享方式。
我们正在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;
}
使用this教程
创建了DLL答案 0 :(得分:10)
绝对不应该混合来自不同版本的运行时的类型。即使它们的大小相同,它们也可能将变量存储在不同的位置,或者某些算法可能会略有变化。即使类型完全相同,不同的编译器也可能选择以不同的方式表示它们。
真的没有好办法做到这一点。 C ++不保证其标准库的实现不会改变,并且编译器似乎无法就ABI(即使在相同编译器的版本之间)达成一致,即使它们没有。在为其他人编写API时,大多数人选择只导出完全由他们控制的C类型。
答案 1 :(得分:-2)
由于我没有不使用不同版本的选项,我认为最接近解决问题的方法是使用指向 STL-containers 的指针而不是直接访问它们(例如{{1而不是std::vector<std::string*>*
)。
如果有可能的话,我仍然非常喜欢非指针解决方案,但至少这样我就不必创建自己的字符串和vector-class作为解决方法。 / p>
<强>更新强>
人们显然不太喜欢这个答案。就个人而言,我认为最好被告知有一个解决方案,而不是被告知根本不应该做的事情。解决方案保存了我们,因为它允许我们继续工作,直到几周后我们可以将所有内容升级到同一个编译器。
虽然批评有一些优点。解决方案虽然工作可能非常危险,但是当单独分配而不是作为结构的一部分时,String类的布局在两个编译器中是相同的,这可能是巧合。
更好的解决方案可能只是:
使用C类型,例如使用
std::vector<std::string>*
代替公开C字符串 直接从DLL访问您的字符串或替换所有您的 带有C字符串的字符串。
我现在认为这是@CoryNelson对.c_str()
的意思,但由于我当时对C类型的无知和缺乏经验,我不明白这一点,我以为我只是被告知它是不可能的,我尝试愚蠢。
同样对于投票的人来说,如果你提供一个解释,为什么而不是我自己猜测,我将不胜感激。只要有理由,我对批评没有任何问题。