如何将 XCTest 与 iOS 应用程序一起加载到进程内存(堆损坏问题)?
How XCTest is loaded to process memory along with iOS App (Heap Corruption issue)?
我的 XCTest 套件发生了非常奇怪的崩溃。
测试目标是 Application tests
,启用了 Allow testing Host Application API
复选框。
Build for active arch only
是。
现在我的测试套件中只有一个测试,它仍然崩溃。
Xcode
说崩溃的原因是“堆损坏”。
我已经看到 the possible reasons 的堆损坏,似乎 none 适用于我的情况。
当使用 Address Sanitiser
和 Behaviour Sanitiser
进行测试时,我得到这样的信息:
测试看起来像这样:
- (void)testHeapCorruption {
MyCppClassDictionary dict;
int file_index1 = 41;
// MyCppClassPtr is custom_ptr<MyCppClass>
MyCppClassPtr data_to1 = new MyCppClass(0, 0, 41);
dict.pushDataItem(data_to1);
MyCppClassPtr data_from1 = dict.find(file_index1);
}
和MyCppClass
像这样:
typedef custom_ptr<MyCppClass> MyCppClassPtr;
MyCppClass::MyCppClass(const void* data, int len, int file_index) : m_file_index(file_index)
{
if(len > 0)
{
m_data = malloc(len);
memcpy(m_data, data, len);
}
this->m_len = len;
m_len_initial = len;
}
MyCppClass::~MyCppClass()
{
if (m_data) free(m_data);
}
void MyCppClassDictionary::pushDataItem(MyCppClassPtr item)
{
assert(item);
assert( item->m_file_index != -1 );
m_undo_map[item->m_file_index] = item;
}
MyCppClassPtr MyCppClassDictionary::find(int file_index)
{
auto it = m_undo_map.find(file_index);
if ( it != m_undo_map.end() )
return it->second;
return 0;
}
A custom_ptr
是一个模板 class,其工作方式类似于 std::shared_ptr
:它存储对对象的引用数,并仅在没有引用时调用析构函数。
只有当 MyCppClass
和 MyCppClassDictionary
的目标代码位于 Application
目标时才会发生崩溃。当我将 classes (MyCppClass2, MyCppClassDictionary2) 和 link 复制到 Test
目标时, 一切正常。
现在是低级部分
在 ApplicationTarget
包中有 ./ApplicationTarget
二进制文件和 PlugIns/TestTarget.xctest/./TestTarget
二进制文件。
当看到TestTarget
二进制的符号时,MyCppClass
函数是“Segment External Symbols”段中的“extern function”。
我认为“Heap corruption”中的“Heap”看起来与此类似:
我想知道:
- 相对于主要目标,
TestTarget
二进制文件是如何准确地加载到进程内存中的。
- 他们有没有可能有不同的堆:一个用于主要目标,一个用于测试目标?
- 是否可以调试在一个堆上分配数据并在另一个堆上释放数据的场景? Inside/before
malloc
,是否可以打印heap
的起始地址?
- 我可以尝试哪种 logging?因为 Address Sanitiser 告诉了问题 post-factum.
想了解问题的根源,但感觉自己的记忆力management/assembly技能不够
非常感谢任何 comments/links。
问题的原因是测试目标和主要目标的目标代码略有不同。
一个 custom_ptr
看起来像这样:
//file custom_ptr.h
template<class T> class custom_ptr
{
#ifdef DEBUG
T* some_debug_pointer;
#endif
};
我在 Preprocessor Definitions
中通过了 DEBUG=1
仅用于主要目标。
所以在主要目标 custom_ptr
中有一个成员 some_debug_pointer
,因此 custom_ptr
对象的大小比在测试目标中大,其中 custom_ptr
没有 some_debug_pointer
成员.
我的 XCTest 套件发生了非常奇怪的崩溃。
测试目标是 Application tests
,启用了 Allow testing Host Application API
复选框。
Build for active arch only
是。
现在我的测试套件中只有一个测试,它仍然崩溃。
Xcode
说崩溃的原因是“堆损坏”。
我已经看到 the possible reasons 的堆损坏,似乎 none 适用于我的情况。
当使用 Address Sanitiser
和 Behaviour Sanitiser
进行测试时,我得到这样的信息:
测试看起来像这样:
- (void)testHeapCorruption {
MyCppClassDictionary dict;
int file_index1 = 41;
// MyCppClassPtr is custom_ptr<MyCppClass>
MyCppClassPtr data_to1 = new MyCppClass(0, 0, 41);
dict.pushDataItem(data_to1);
MyCppClassPtr data_from1 = dict.find(file_index1);
}
和MyCppClass
像这样:
typedef custom_ptr<MyCppClass> MyCppClassPtr;
MyCppClass::MyCppClass(const void* data, int len, int file_index) : m_file_index(file_index)
{
if(len > 0)
{
m_data = malloc(len);
memcpy(m_data, data, len);
}
this->m_len = len;
m_len_initial = len;
}
MyCppClass::~MyCppClass()
{
if (m_data) free(m_data);
}
void MyCppClassDictionary::pushDataItem(MyCppClassPtr item)
{
assert(item);
assert( item->m_file_index != -1 );
m_undo_map[item->m_file_index] = item;
}
MyCppClassPtr MyCppClassDictionary::find(int file_index)
{
auto it = m_undo_map.find(file_index);
if ( it != m_undo_map.end() )
return it->second;
return 0;
}
A custom_ptr
是一个模板 class,其工作方式类似于 std::shared_ptr
:它存储对对象的引用数,并仅在没有引用时调用析构函数。
只有当 MyCppClass
和 MyCppClassDictionary
的目标代码位于 Application
目标时才会发生崩溃。当我将 classes (MyCppClass2, MyCppClassDictionary2) 和 link 复制到 Test
目标时, 一切正常。
现在是低级部分
在 ApplicationTarget
包中有 ./ApplicationTarget
二进制文件和 PlugIns/TestTarget.xctest/./TestTarget
二进制文件。
当看到TestTarget
二进制的符号时,MyCppClass
函数是“Segment External Symbols”段中的“extern function”。
我认为“Heap corruption”中的“Heap”看起来与此类似:
我想知道:
- 相对于主要目标,
TestTarget
二进制文件是如何准确地加载到进程内存中的。 - 他们有没有可能有不同的堆:一个用于主要目标,一个用于测试目标?
- 是否可以调试在一个堆上分配数据并在另一个堆上释放数据的场景? Inside/before
malloc
,是否可以打印heap
的起始地址? - 我可以尝试哪种 logging?因为 Address Sanitiser 告诉了问题 post-factum.
想了解问题的根源,但感觉自己的记忆力management/assembly技能不够
非常感谢任何 comments/links。
问题的原因是测试目标和主要目标的目标代码略有不同。
一个 custom_ptr
看起来像这样:
//file custom_ptr.h
template<class T> class custom_ptr
{
#ifdef DEBUG
T* some_debug_pointer;
#endif
};
我在 Preprocessor Definitions
中通过了 DEBUG=1
仅用于主要目标。
所以在主要目标 custom_ptr
中有一个成员 some_debug_pointer
,因此 custom_ptr
对象的大小比在测试目标中大,其中 custom_ptr
没有 some_debug_pointer
成员.