2

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 ?

Gossamer
  • 309
  • 2
  • 16
  • 2
    If you calloc m_size bytes, you should only write to 0..m_size-1. Writing to buffer[m_head] when m_head == m_size will usually trigger the exception. – ott-- Oct 15 '12 at 20:06

2 Answers2

2

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).

0x5f3759df
  • 180
  • 3
  • 5
  • Ok, basically i made a bug. I forgot to include if (m_head == m_size) m_head = 0; at the end of code ... I cannot verify right now if that caused this specific problem. Most probably, but i will add comment when i verify it. Thanx for pointing out the ARC facts. – Gossamer Oct 16 '12 at 07:59
  • Yeah, that was it .. Sorry Apple, nothing to with implementation of ARC :) Thanx. – Gossamer Oct 16 '12 at 18:46
1

After you reached if-condition is TRUE, overflow is set to TRUE. But, this program never reset overflow to FALSE. So, m_head is continue to grow much. Never reset to ZERO. Result, buffer[m_head] access out of reserved memory.

ok?

koki
  • 352
  • 1
  • 7