将指针作为参数传递给slave dll错误的对象大小

时间:2016-06-23 11:10:30

标签: c++ c visual-studio-2010 visual-c++ master-slave

我有两个模块。一个人调用另一个,并将结构作为参数传递。

struct {
    char* szDGRTag;
    bool bTagEx;
} ADPTAG;

Master是用C ++编写的,来自Visual C ++ 6.0中的' 98。 Slave是用Visual Studio 2010 Professional中的C ++ 11编写的 在Slave中调用的函数:

long lCheckPresenceOfFields (char* szName, ADPTAG* AdpTagList, long lNbVar)

在主人:

long lNbVar = 2;
ADPTAG* AdpTagList = NULL;
AdpTagList = new ADPTAG[lNbVar];

AdpTagList[0].szTag = new char[32];
AdpTagList[0].bTagEx = true;
memset(AdpTagList[0].szTag, 0x0, 32+1);
AdpTagList[0].szTag = NULL;

AdpTagList[1].szTag = new char[32]; 
AdpTagList[1].bTagEx = true;
memset(AdpTagList[1].szTag, 0x0, 32+1);
AdpTagList[1].szTag = NULL;

int size = sizeof(AdpTagList[0]);
AdpTagList[0].szTag = "DDD";
AdpTagList[1].szTag = "AAA";

long pres = pGetFieldsPresence(szPath, AdpTagList, 2);

我在Master中检查了AdpTagList [0]的大小并且它是5个字节,但是在Slave中它是8个字节,所以第一个对象是OK,但是下一个是坏的,因为指针指向错误的内存区域。
这可能是什么问题?不同的编译器?可能不是只有char *和int的结构在这两个模块之间工作正常 无论第一个对象[0]的大小如何,第二个[1]都是空指针。

2 个答案:

答案 0 :(得分:3)

您遇到了包装差异。您可以使用"/Zp" compiler option修改打包。

默认情况下,Visual Studio:

  

在8字节边界上打包结构

您的Visual Studio 2010编译器很可能没有指定打包。您的Visual C ++ 6.0应用程序可能确实指定了1字节打包,因为包含intchar的结构应包含在其中。

使用1字节打包可优化程序系统内存占用,因为填充不会丢失内存。

使用8字节打包可以优化速度,因为它增加了在单个负载中获取结构的机会。

有关包装的更多信息,请参阅此处:https://msdn.microsoft.com/en-us/library/71kf49f1.aspx

但我会依据微软的声明:

  

除非您有特定的对齐要求,否则不应使用此选项

因为您必须更改一个,所以我建议您更改Visual C ++ 6.0应用程序的打包。

答案 1 :(得分:2)

是的,它的编译器差异应该归咎于它。在二进制级别上没有C ++的标准化。特别是这意味着任何编译器都可以自由选择自己的结构填充规则,这就是影响你的方法。显然,最近的编译器决定添加3个字节的填充以使结构64位对齐,但较旧的编译器不会这样做。

通常,无法确保两个不同编译器生成的数据之间的二进制兼容性。您可以切换到使用字节流,也可以为两者使用相同的编译器。