2

我正在使用 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 解决方案。

这段代码使用 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 编译。

主文件

#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

4

2 回答 2

10

您绝对不应该混合来自不同版本的运行时的类型。即使它们的大小相同,它们也可能将变量存储在不同的位置,或者某些算法可能会略有变化。即使类型完全相同,不同的编译器也可能选择以不同的方式表示它们。

确实没有什么好的方法可以做到这一点。C++ 不保证其标准库的实现不会改变,编译器似乎无法就 ABI 达成一致(即使在同一编译器的版本之间),即使它们没有达成一致。在编写 API 供他人使用时,大多数人选择只导出完全在他们控制之下的 C 类型。

于 2012-12-30T21:54:40.913 回答
-2

由于我没有不使用不同版本的选项,我认为最接近解决问题的方法是使用指向STL 容器的指针而不是直接访问它们(例如std::vector<std::string*>*,而不是std::vector<std::string>*)。

如果可能的话,我仍然非常喜欢非指针解决方案,但至少这样我就不必发明自己的字符串和向量类作为解决方法。

视觉工作室内的指针


更新

人们显然不太喜欢这个答案。就我个人而言,我认为最好被告知有解决方案,而不是被告知根本不应该做某事。该解决方案拯救了我们,因为它允许我们继续工作,直到几周后我们可以将所有内容升级到相同的编译器。

虽然,批评有一些优点。该解决方案虽然可行,但可能非常危险,并且当单独分配而不是作为结构的一部分分配时,两个编译器中的 String 类的布局可能是相同的,这可能是一个巧合。

更好的解决方案可能只是:

改用 C 类型,例如使用.c_str()公开 C 字符串而不是直接从 DLL 访问您的字符串或用 C 字符串替换所有字符串。

我现在认为这就是@CoryNelson 的意思most people choose to export only C types,但由于我当时对 C 类型的无知和缺乏经验,我不明白这一点,我以为我只是被告知这是不可能的,我很愚蠢试。

如果您提供解释而不是我自己猜测的原因,那么对于投反对票的人来说,将不胜感激。只要给出理由,我对批评没有意见。

于 2013-01-01T23:51:47.667 回答