Search code examples
iosautomatic-ref-countingcalloc

ARC is releasing calloc'ed memory?


Something strange is going on in my code. Basically im doing the network stream application that transfers some data into ring buffer memory on iOS and then afterwards read the memory. I was getting EXC_BAD_ACCESS after some undetermined amount of data. So i enabled NSZombieEnabled and NSAutoreleaseFreedObjectCheckEnabled and setted the malloc_error_break and was able to pinpoint the cause of error.

My MainClass have the property (also tried with strong reference, same behaviour)

@property (nonatomic, retain) RingBuffer *readBuffer;

in the RingBuffer class im initialising the buffer size as:

-(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;
}

after, i use the push method to insert data in 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;
}

If i remove the push call, application will not crash. If the push call is called it will crash after some time. Sometimes i get 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... Sometimes it is just EXC_BAD_ACCESS.

Basically, what i don't understand is why is this causing the issue ? Is it possible that ARC released the calloced memory ?


Solution

  • Is it possible that ARC released the calloced memory ?

    No, that is not possible. ARC, which is an abbreviation for Automatic Reference Counting, is a compiler feature that, if enabled, provides automatic memory management of Objective C objects, by inserting release, retain and autorelease memory calls directly into your compiled code. Since buffer is not an Objective C object, but a pointer to an allocated block of memory on the heap, which is not released by ARC. It is your obligation to free this allocated block of memory yourself.

    To learn more about how ARC works, checkout Apple's WWDC 2011 session video: Introducing Automatic Reference Counting.

    Basically, what i don't understand is why is this causing the issue ?

    Hard to say, but the issue could be that m_head is only set to zero if m_head == size && overflow == FALSE. This condition is ONLY true the first time m_head equals m_size, (because overflow == FALSE), but will no longer be true the next time m_head equals m_size, because overflow equals TRUE (and m_head will not be reset to 0).