Xcode 中 c++ 结构的内存布局不一致
Inconsistent memory layout of c++ struct in Xcode
我在 iPhone 模拟器上执行通过 XCode 版本 9.2 (9C40b) 编译(和调试)的 c++ 代码时遇到问题。
代码片段如下;所有涉及的文件都是同一个库的一部分,该库稍后链接到 iPhone 应用程序以执行。请注意,截取的已发布代码已针对调查目的进行了自定义和缩减,最初它用于不同的目的,但隔离 'offending lines' -.-
已经足够痛苦了
// HEADER FILE struct_definition.h CONTAINING STRUCT DECLARATION
struct SRowLogBookDescriptor
{
SRowLogBookDescriptor();
mutable u32 key ;
std::string name ;
std::string ui_name ;
u32 type ;
u32 physical_quantity ;
std::string unit_of_measure ;
u32 constraints_size ;
u8* constraints ;
std::string comment ;
u64 marker;
};
//---------------------------------------------
// SOURCE FILE struct_definition.cpp CONTAINING STRUCT CONSTRUCTOR DEFINITION
SRowLogBookDescriptor::SRowLogBookDescriptor()
: key(0xFFFFFFFF)
, name("name")
, ui_name("ui_name")
, type(0xAAAAAAAA)
, physical_quantity(0x55555555)
, unit_of_measure("unit")
, constraints_size(0xB5006BB1)
, constraints(nullptr)
, comment("comment")
, marker(0xBAD00DABBAD00DAB)
{}
//---------------------------------------------
// SOURCE FILE function_call.cpp USING THE MISALIGNED STRUCTURE
void CDefaultLogbookSet::AddDoubleLogBookToSet()
{
SRowLogBookDescriptor descr;
int i1 = offsetof(SRowLogBookDescriptor,key) ;
int i2 = offsetof(SRowLogBookDescriptor,name) ;
int i3 = offsetof(SRowLogBookDescriptor,ui_name) ;
int i4 = offsetof(SRowLogBookDescriptor,type) ;
int i5 = offsetof(SRowLogBookDescriptor,physical_quantity) ;
int i6 = offsetof(SRowLogBookDescriptor,unit_of_measure) ;
int i7 = offsetof(SRowLogBookDescriptor,constraints_size) ;
int i8 = offsetof(SRowLogBookDescriptor,constraints) ;
int i9 = offsetof(SRowLogBookDescriptor,comment) ;
int i10 = offsetof(SRowLogBookDescriptor,marker);
size_t test1 = descr.name.capacity();
size_t test2 = descr.ui_name.capacity();
descr.comment = "";
descr.name = "new_name";
descr.physical_quantity = 0xaa;
descr.type = 0x55;
descr.ui_name = "new_ui_name";
descr.unit_of_measure = "new_unit";
}
//---------------------------------------------
我有一个包含 32 位整数、字符串和指针的结构。我很清楚结构的对齐布局会由于填充而导致字节浪费。我已经检测了结构的构造函数,以突出显示每个字段映射到内存的位置。
然后在 AddDoubleLogBookToSet 函数中将结构放在堆栈上,我将所有字段的偏移量保存在结构中,我检查字符串容量,填充值,然后函数退出。
当我尝试为 name 字段赋值时,我得到一个 BAD_ACCESS 异常。当我实际遇到异常时,我附上了从 XCode 调试器截取的 2 个屏幕截图。
在那里您可以看到结构属性的预期偏移量,以及您可以看到调试器实际上在实际未存储属性的内存位置访问属性。
我刚刚检查了调试器,当我执行构造函数时,调试器 'sees' 结构成员适当(我没有附上截图)。
现在...在我看来 function_call.cpp 和 struct_definition.cpp 在打包 and/or 对齐方面存在某种编译差异。
我已经多次检查代码中的每个pragma pack每次都被适当清除,显然检查代码,一切正常。
让我补充一点,在 Xcode 中编译的相同 C++ 代码正在通过 Visual Studio 2017 编译的不同 Windows 版本(PC)上顺利编译和执行。
调查的开始是因为大量不同的崩溃都与包含违规代码的库有关(该库中有几个不同的结构)。
最后但并非最不重要的一点是,iPhone 应用程序在很长一段时间内一直运行良好,然后在几周前停止正常运行。
问题来了:谁能帮我找出为什么这两个源文件的编译方式不同?
提前致谢
嗯,找到问题所在了
我创建了一个与违规源文件完全相同的新源文件,进一步缩减了其内容以方便调查。我编译了文件并开始创建 class 修剪代码的实例,其中它导致了问题与没有导致问题。
最后发现有一个 'remote header' 文件,其中声明了打包结构,其中包含 pragma 包内的指令。将那些包含从特殊包装中移除,使编译在所有文件中再次保持一致。与 Visual Studio 编译过程相比,包含树在 Xcode 编译过程中尤其有害。
才几天就知道了-.-'
我在 iPhone 模拟器上执行通过 XCode 版本 9.2 (9C40b) 编译(和调试)的 c++ 代码时遇到问题。
代码片段如下;所有涉及的文件都是同一个库的一部分,该库稍后链接到 iPhone 应用程序以执行。请注意,截取的已发布代码已针对调查目的进行了自定义和缩减,最初它用于不同的目的,但隔离 'offending lines' -.-
已经足够痛苦了// HEADER FILE struct_definition.h CONTAINING STRUCT DECLARATION
struct SRowLogBookDescriptor
{
SRowLogBookDescriptor();
mutable u32 key ;
std::string name ;
std::string ui_name ;
u32 type ;
u32 physical_quantity ;
std::string unit_of_measure ;
u32 constraints_size ;
u8* constraints ;
std::string comment ;
u64 marker;
};
//---------------------------------------------
// SOURCE FILE struct_definition.cpp CONTAINING STRUCT CONSTRUCTOR DEFINITION
SRowLogBookDescriptor::SRowLogBookDescriptor()
: key(0xFFFFFFFF)
, name("name")
, ui_name("ui_name")
, type(0xAAAAAAAA)
, physical_quantity(0x55555555)
, unit_of_measure("unit")
, constraints_size(0xB5006BB1)
, constraints(nullptr)
, comment("comment")
, marker(0xBAD00DABBAD00DAB)
{}
//---------------------------------------------
// SOURCE FILE function_call.cpp USING THE MISALIGNED STRUCTURE
void CDefaultLogbookSet::AddDoubleLogBookToSet()
{
SRowLogBookDescriptor descr;
int i1 = offsetof(SRowLogBookDescriptor,key) ;
int i2 = offsetof(SRowLogBookDescriptor,name) ;
int i3 = offsetof(SRowLogBookDescriptor,ui_name) ;
int i4 = offsetof(SRowLogBookDescriptor,type) ;
int i5 = offsetof(SRowLogBookDescriptor,physical_quantity) ;
int i6 = offsetof(SRowLogBookDescriptor,unit_of_measure) ;
int i7 = offsetof(SRowLogBookDescriptor,constraints_size) ;
int i8 = offsetof(SRowLogBookDescriptor,constraints) ;
int i9 = offsetof(SRowLogBookDescriptor,comment) ;
int i10 = offsetof(SRowLogBookDescriptor,marker);
size_t test1 = descr.name.capacity();
size_t test2 = descr.ui_name.capacity();
descr.comment = "";
descr.name = "new_name";
descr.physical_quantity = 0xaa;
descr.type = 0x55;
descr.ui_name = "new_ui_name";
descr.unit_of_measure = "new_unit";
}
//---------------------------------------------
我有一个包含 32 位整数、字符串和指针的结构。我很清楚结构的对齐布局会由于填充而导致字节浪费。我已经检测了结构的构造函数,以突出显示每个字段映射到内存的位置。
然后在 AddDoubleLogBookToSet 函数中将结构放在堆栈上,我将所有字段的偏移量保存在结构中,我检查字符串容量,填充值,然后函数退出。
当我尝试为 name 字段赋值时,我得到一个 BAD_ACCESS 异常。当我实际遇到异常时,我附上了从 XCode 调试器截取的 2 个屏幕截图。
我刚刚检查了调试器,当我执行构造函数时,调试器 'sees' 结构成员适当(我没有附上截图)。
现在...在我看来 function_call.cpp 和 struct_definition.cpp 在打包 and/or 对齐方面存在某种编译差异。 我已经多次检查代码中的每个pragma pack每次都被适当清除,显然检查代码,一切正常。
让我补充一点,在 Xcode 中编译的相同 C++ 代码正在通过 Visual Studio 2017 编译的不同 Windows 版本(PC)上顺利编译和执行。 调查的开始是因为大量不同的崩溃都与包含违规代码的库有关(该库中有几个不同的结构)。 最后但并非最不重要的一点是,iPhone 应用程序在很长一段时间内一直运行良好,然后在几周前停止正常运行。
问题来了:谁能帮我找出为什么这两个源文件的编译方式不同?
提前致谢
嗯,找到问题所在了
我创建了一个与违规源文件完全相同的新源文件,进一步缩减了其内容以方便调查。我编译了文件并开始创建 class 修剪代码的实例,其中它导致了问题与没有导致问题。
最后发现有一个 'remote header' 文件,其中声明了打包结构,其中包含 pragma 包内的指令。将那些包含从特殊包装中移除,使编译在所有文件中再次保持一致。与 Visual Studio 编译过程相比,包含树在 Xcode 编译过程中尤其有害。
才几天就知道了-.-'