如何将 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 SanitiserBehaviour 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:它存储对对象的引用数,并仅在没有引用时调用析构函数。

只有当 MyCppClassMyCppClassDictionary 的目标代码位于 Application 目标时才会发生崩溃。当我将 classes (MyCppClass2, MyCppClassDictionary2) 和 link 复制到 Test 目标时, 一切正常。


现在是低级部分

ApplicationTarget 包中有 ./ApplicationTarget 二进制文件和 PlugIns/TestTarget.xctest/./TestTarget 二进制文件。

当看到TestTarget二进制的符号时,MyCppClass函数是“Segment External Symbols”段中的“extern function”。

我认为“Heap corruption”中的“Heap”看起来与此类似:

我想知道:

  1. 相对于主要目标,TestTarget 二进制文件是如何准确地加载到进程内存中的。
  2. 他们有没有可能有不同的堆:一个用于主要目标,一个用于测试目标?
  3. 是否可以调试在一个堆上分配数据并在另一个堆上释放数据的场景? Inside/before malloc,是否可以打印heap的起始地址?
  4. 我可以尝试哪种 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 成员.