【问题标题】:ARC is releasing calloc'ed memory?ARC 正在释放 calloc'ed 内存?
【发布时间】:2012-10-15 19:38:12
【问题描述】:

我的代码中发生了一些奇怪的事情。基本上我在做网络流应用程序,将一些数据传输到 iOS 上的环形缓冲区内存中,然后读取内存。 在一些不确定的数据量之后,我得到了EXC_BAD_ACCESS。所以我启用了NSZombieEnabledNSAutoreleaseFreedObjectCheckEnabled 并设置了malloc_error_break 并且能够查明错误的原因。

我的MainClass 拥有该属性(也尝试过强引用,相同的行为)

@property (nonatomic, retain) RingBuffer *readBuffer;

RingBuffer 类中,我将缓冲区大小初始化为:

-(id) initWithSize: (NSInteger) size
{
    self = [super init];
    m_size = size;
    buffer = (unsigned char *)calloc(m_size, sizeof(unsigned char));
    overflow = FALSE;
    m_tail = 0;
    m_head = 0;
    error = 0;
    return self;
}

之后,我使用 push 方法在 ringbuffer 中插入数据

- (void) push: (unsigned char) byte
{
    if (m_head == m_size && overflow == FALSE) {
        m_head = 0;
        overflow = TRUE;
        }
    buffer[m_head] = byte;
    m_head ++;
    if (overflow) m_tail++;
    if (m_tail == m_size) m_tail = 0;
}

如果我删除推送调用,应用程序不会崩溃。如果调用推送调用,它会在一段时间后崩溃。有时我得到alloc: *** error for object 0x1cad3404: incorrect checksum for freed object - object was probably modified after being freed. *** set a breakpoint in malloc_error_break to debug...有时它只是EXC_BAD_ACCESS。

基本上,我不明白为什么会导致这个问题? ARC是否有可能释放了calloced内存?

【问题讨论】:

  • 如果你调用 m_size 字节,你应该只写入 0..m_size-1。当 m_head == m_size 时写入缓冲区[m_head] 通常会触发异常。

标签: ios automatic-ref-counting calloc


【解决方案1】:

ARC 是否有可能释放了 calloced 内存?

不,这是不可能的。 ARC 是 Automatic Reference Counting 的缩写,是一种编译器功能,如果启用,它可以通过将释放、保留和自动释放内存调用直接插入到编译代码中来提供 Objective C 对象的自动内存管理。由于buffer 不是Objective C 对象,而是指向堆上已分配内存块的指针,ARC 不会释放该内存块。您有义务自己释放这块已分配的内存。

要详细了解 ARC 的工作原理,请观看 Apple 的 WWDC 2011 会议视频:Introducing Automatic Reference Counting

基本上,我不明白为什么会导致这个问题?

很难说,但问题可能是 m_head 仅在 m_head == size && overflow == FALSE 时设置为零。此条件仅在第一次 m_head 等于 m_size 时为真,(因为溢出 == FALSE),但下次 m_head 等于 m_size 时将不再为真,因为 overflow 等于 TRUE(并且m_head 不会被重置为 0)。

【讨论】:

  • 好的,基本上我犯了一个错误。我忘了包括 if (m_head == m_size) m_head = 0;在代码末尾......我现在无法验证这是否导致了这个特定问题。很可能,但我会在验证时添加评论。感谢您指出 ARC 的事实。
  • 是的,就是这样 .. 对不起 Apple,与 ARC 的实施无关 :) 谢谢。
【解决方案2】:

如果条件为 TRUE,则溢出设置为 TRUE。 但是,这个程序永远不会将溢出重置为 FALSE。 所以,m_head 是继续增长的。 永远不要重置为零。 结果,buffer[m_head] 访问超出保留内存。

好吗?

【讨论】:

    猜你喜欢
    • 2013-12-17
    • 2012-05-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多