应用程序和exe之间的类大小更改

时间:2012-01-17 08:42:47

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

我有一个控制台应用程序来实例化一个类(比如class X)。该类在dll中定义 - > X.dll。当我在应用程序中打印类的大小和类的一个函数(在应用程序调用它时调用它)时 - 我注意到大小的变化。

我正在使用VS 2010,应用程序打印类大小为6304,函数打印为6352.我在Release | Win32模式下编译了exe和dll。两者都定义了WIN32_WINDOWS。但是没有定义WIN64

我注意到的更多是当我在exe中打印sizeof(time_t)时,它打印4并且dll中的函数打印8.认为这可能是个问题。

我知道应该在哪里检查?

3 个答案:

答案 0 :(得分:7)

我同意,如果DLL和EXE 在数据类型布局 上存在分歧,则可能会出现问题。

但是,除了您必须在两个项目之间使用 不同的项目设置 之外,我看不到任何其他解释。

为了找到罪魁祸首, 在解决方案中标记两个项目 Ctrl +左键单击),然后打开属性对话框。该对话框现在仅显示所选配置中两个项目的 属性 。尽管对话框乍一看似乎是模态对话,但您可以单击其中一个项目以仅查看其属性,还可以再次标记它们,这样您就可以 切换回来在这些观点之间 。到目前为止,我经常发现使用这种技术的问题。

如果此操作失败,您始终可以 比较项目文件 。他们是非常健谈的XML文件使得这更难。

答案 1 :(得分:2)

Alignment problem

我已经不得不处理同一类的不同大小。

这最多导致崩溃(因为你的代码会尝试读取/写入超出类的实际数据),最坏的情况是奇怪的错误(比如将成员变量的值设置为42,然后读取它看到的值是1376256或类似的东西。)

原因通常与对齐问题有关。

这是你可以做的,看看你的问题是否是对齐问题:

在课程定义之前(或之后),添加以下行:

#pragma pack(show)

在编译输出中,您应该看到类似的内容:

1>。\ test_align.cpp(59):警告C4810:pragma pack的值(显示)== 8

这将显示编译头时的对齐方式。每次标题包含在CPP文件中时都会出现这种情况。在DLL编译和EXE编译中,该值始终是相同的。

如果它们不同,甚至一次,那么你就会出现错位问题......

项目的默认结构对齐?

也许你的DLL的默认结构对齐设置为1,而EXE有另一个值。 请检查项目的两个属性: “C / C ++”部分,“代码生成”小节,属性“Struct Member Alignment”。

要使一切正常工作,两个项目都应具有相同的值。

如果EXE和DLL具有不同的值,则必须更正(“默认”值通常是好的:选择“从父​​级或项目值继承”)。

Pragma pack?

还有另一种方法可以打破对齐,即通过使用#pragma pack语句。例如:

#pragma pack(show) // this will show the default value, i.e. 8 on my project

struct Data8       // the sizeof this struct is 8 bytes
{
   bool     m_bValue ;
   int      m_iValue ;
} ;

#pragma pack(push, 1)

#pragma pack(show) // this will show the now current value, i.e. 1

struct Data1       // the sizeof this struct is 5 bytes, thanks to the packing
{
   bool     m_bValue ;
   int      m_iValue ;
} ;

#pragma pack(pop)

#pragma pack(show) // this will show again the default value, i.e. 8

因此,搜索#pragma pack语句,并验证它们是否始终正确设置和取消设置(如果你有一个没有弹出的推送,那么你可能有错误。)

该类在两个项目中具有相同的对齐方式?

如果你没有在你的类中发现问题,那么问题可能在于它继承的类/结构之一,或者它具有成员变量。

所以验证它们,就像验证主类一样。

答案 2 :(得分:2)

在VS 2010中,time_t类型应为64位值(构建目标是32位还是64位)。这可以通过定义_USE_32BIT_TIME_T来覆盖32位目标构建 - 因此您应确保未在应用程序构建中定义(或者如果需要在那里定义,则还需要定义它适用于您的DLL或在DLL类定义中使用__time32_t类型。

我还要确保您没有为DLL和应用程序构建设置不同的打包选项(请注意,可以在写得不好的头文件中更改打包配置)。在构建日志中查找/Zp编译器选项和/或头文件中的#pragma pack行,而没有重置为默认设置的相应#pragma pack()