【问题标题】:ARC & Malloc: EXEC_BAD_ACCESSARC 和 Malloc:EXC_BAD_ACCESS
【发布时间】:2012-02-25 12:49:09
【问题描述】:

我从事一个项目已经有一段时间了,我决定跳到 ARC。 我遇到了一些每次都被炸毁的代码,我想知道为什么。我设法将其简化为这个 sn-p:

typedef __strong id MYID;

int main(int argc, char *argv[])
{ 
    MYID *arr = (MYID *) malloc(sizeof(MYID) * 4);

    arr[0] = @"A";     // always get an EXEC_BAD ACCESS HERE
    arr[1] = @"Test";
    arr[2] = @"Array";
    arr[3] = @"For";

    // uh oh, we need more memory
    MYID *tmpArray = (MYID *) realloc(arr, sizeof(MYID) * 8);
    assert(tmpArray != NULL);

    arr = tmpArray;

    arr[4] = @"StackOverflow";  // in my actual project, the EXEC_BAD_ACCESS occurs here
    arr[5] = @"Is";
    arr[6] = @"This";
    arr[7] = @"Working?";

    for (int i = 0; i < 8; i++) {
        NSLog(@"%@", arr[i]);
    }

    return 0;
}

我不太确定这里发生了什么,在 4 个不同的项目中对此感到厌烦,但它们都失败了。我的malloc 电话有问题吗?有时它返回 null,有时它返回一个我无法访问的指针。

【问题讨论】:

  • 为什么是 typedef?没有其他限定的对象指针被假定为__strong
  • 因为在实际项目中,MYID是一个struct(cocos2d的ccCArray)的一部分。此外,如果没有所有权限定符,代码将无法编译,因为它不是所有者可能是“自我”的选择器的一部分。
  • 我不确定您所说的“因为它不是选择器的一部分,其中所有者可能是'自己'”。在方法中分配的对象的“所有者”是堆栈本身,而不是self 的值。另请注意,您不能将__strong(或__weak)对象指针放入ARC下的C结构中,您必须使用__unsafe_unretained并显式管理内存(例如,使用一些非ARC代码或CFRetain()/@ 987654330@).
  • 归档 要求编译器对此模式发出警告/错误。
  • 或者你可以使用Objective-C++,它支持结构中的ARC指针。 (如果您将 ARC 指针放入其中,它们将是非 POD 结构。)

标签: objective-c c malloc automatic-ref-counting realloc


【解决方案1】:

崩溃是因为您将 malloc 的内存转换为 C 对象数组。当您尝试分配给其中一个插槽时,ARC 将释放先前的值,这将是垃圾内存。尝试使用calloc() 而不是malloc() 将内存归零,它应该可以工作。

请注意,您的 realloc() 调用也不会对分配的任何新内存进行零填充,因此,如果您需要 realloc(),那么您可能希望使用一个临时的 void* 指针,然后手动进行零填充在分配给您的对象数组之前。

【讨论】:

  • 该死。微妙的。在这种情况下,您必须非常了解保留/释放/C 才能使用 ARC。
  • @nielsbot:只要你坚持使用 Obj-C,你应该没有问题。这种事情只有在尝试将基本的 C 内容(如 malloc())与 ARC 结合时才会出现。
  • 另外,如果 malloc 的数组只是用于临时存储 id 的函数范围,你不能使用 (__unsafe_unretained MYID*) 代替 (MYID*) 吗?
  • @nielsbot:我承认如果你分配/初始化一个对象并将其分配给__unsafe_unretained 插槽,我不太确定 ARC 会做什么。我认为它完全忽略了这些引用,因此它可能会释放该对象。但是使用__autoreleasing 可能会起作用。尽管如果您使用的是 ARC,那么您可能希望保留显式的生命周期语义。我知道如果我需要使用这个成语,我个人只会确保内存是零填充的。
  • @nielsbot 问题是,它不是临时存储,它使用强对象是有原因的,它是一个管理节点(子节点、层等)事物的数组。跨度>
【解决方案2】:

malloc 函数不会将其分配的内存归零。内存可以包含随机垃圾。

来自Clang Automatic Reference Counting 指南,第 4.2 节:

对于__strong对象,首先保留新的pointee;其次,左值加载了原始语义;第三,新的指针对象以原始语义存储到左值中;最后,旧指针被释放

所以这里可能发生的是malloc 正在返回包含随机非零值的内存。 ARC 尝试使用该随机值作为指向对象的指针并释放它,但它不是有效的对象指针。崩溃。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-07-18
    • 2012-01-31
    • 1970-01-01
    • 1970-01-01
    • 2014-10-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多