【发布时间】:2018-06-07 09:23:38
【问题描述】:
我在 iPhone 模拟器上执行通过 XCode 版本 9.2 (9C40b) 编译(和调试)的 c++ 代码时遇到问题。
代码sn-p如下;所有涉及的文件都是同一个库的一部分,该库稍后链接到 iPhone 应用程序以供执行。请注意,为了调查目的,已截取发布的代码已被定制和修剪,最初它用于不同的目的,但隔离“违规行”已经足够痛苦了-.-
// 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 个屏幕截图。 在那里您可以看到 struct 属性的预期偏移量,并且您可以看到调试器实际上是在实际未存储属性的内存位置访问属性。
我刚刚检查了调试器,当我执行构造函数时,调试器会适当地“看到”结构成员(我没有为此附上屏幕截图)。
现在...在我看来,function_call.cpp 和 struct_definition.cpp 在打包和/或对齐方面存在某种编译差异。 我已经多次检查代码中的每个编译指示包每次都被适当地清除,并且显然审查了代码,一切正常。
让我补充一点,在 Xcode 中编译的相同 c++ 代码正在通过 Visual Studio 2017 编译的不同 Windows 版本(PC)上顺利编译和执行。 调查的开始是因为大量不同的崩溃都与包含违规代码的库相关(该库中有几个不同的结构)。 最后但并非最不重要的一点是,iPhone 应用程序在很长一段时间内一直运行良好,然后在几周前就停止了正常运行。
问题是:有人可以帮我找出为什么这两个源文件的编译方式不同吗?
提前致谢
【问题讨论】:
-
清理并重建 - 钱说有些东西没有正确重新编译
-
也许,
desc是否来自函数的 reference 参数,以及来自该函数的 caller 的动态分配,以及所述分配使用 C 语义天真地分配?更糟糕的是,这个结构是否天真地从某个文件或内存支持的缓冲区中作为一个 blob 流式传输,作为一个过渡?一旦你说,具有 C++ 结构的“pragma pack”和非平凡的成员巨大的危险信号就出现了。如果您将其作为流中的 blob 进行字节读取,坏主意。 -
@UKMonkey - 清理和重建已执行无数次,包括删除所有 Xcode 的 DerivedData。
-
@WhozCraig - (根据发布的代码)结构实例在没有参数的普通函数堆栈上创建为一个简单变量。这会触发编码的默认构造函数的调用。这种结构不会被任何东西流式传输。上面的结构不应该被打包,其他结构是流式传输和打包的,但这些不是,因为我们通常远离你提到的那些危险信号;)出于未知原因,我们正在努力解决这些问题危险信号,但我们不知道是谁在我们的源文件中植入了这些标记:(