2

I am opening an audio file to read it and I get an abandoned malloc block from this caller each time.

In a loop I set data like this (which is marked as the memory usage in instruments as 99.7%) data = (short*)malloc(kSegmentSize*sizeof(short));

and free it like this free(data); at the end of each iteration.

Im not really sure what is happening here and would appreciate any help.

EDIT: KSegmentSize varies in the thousands, from minimum 6000 - max 50000 (speculative)

Instruments trace:

enter image description here

enter image description here

some_id
  • 29,466
  • 62
  • 182
  • 304
  • what is the value of kSegmentSIze ? – Nick Maroulis Mar 18 '13 at 01:09
  • @marabutt int kSegmentSize = (int)(numberOfFramesPerCycle * mExtAFNumChannels * mExtAFRateRatio + .5); – some_id Mar 18 '13 at 02:05
  • @Helium3 It seems from the stack trace that the leak happens inside `ExtAudioFileOpeURL()` and while `new`ing an array of some kind, and not from your code while calling `malloc()`. I might be completely wrong, but maybe you are calling that function incorrectly? Maybe it returns a buffer to you that *you* are supposed to release but you don't? Maybe it has a bug? (Although if this is a library bug, it's a huge one!) Could you post the code for the loop? That may help us help you! – yzt Mar 23 '13 at 04:53
  • Memory tools often have false negative pointing to `caches` as a source of memory leaks. The `ExtAudioFileOpeURL()` may place buffered data from the file in a `cache`. Especially common in this behavior is DNS/name service lookups. If you constantly do the same name lookup (think http/1.0), then the `libc` will cache the name lookup so you don't continually send to the network. If the leak is recurring, with the same call parameters, then this is not the issue. – artless noise Mar 24 '13 at 04:57
  • Hi, I commented out all the code related to the data malloc and free and just open the files now. I still get the same leak and instruments flags this line of code as 100% err = ExtAudioFileOpenURL((__bridge CFURLRef)fileURL, &mExtAFRef); I do call close file on the reader, but the leak remains. Not sure what is going on here other than a leak when bridging. I would appreciate any help on this. – some_id Mar 26 '13 at 23:59

3 Answers3

1

Not having the exact code:

Pretty sure you're having this problem b/c something between the malloc and free is throwing (and you're probably catching it already so you don't exit the loop). Depending on if this is happening in C (or objective-C) or C++ code, you have slightly different methods of resolution.

In C++, wrap the malloc/free in the RAII pattern so that when the stack is unwound the free is called.

class MyData {
public:
    A(size_t numShorts) : dataPtr(0) { dataPtr = malloc(numShorts * sizeof(short)); }
    ~A() { free(dataPtr); }
    operator short*() { return dataPtr; }
private:
    short* dataPtr;
}

MyData data(numShorts);
// do your stuff, you can still use data as you were before due the 'operator short*'
// allow the dtor to be called when you go out of scope

In Objective-C you need to use a finally block:

void* myPtr = 0;
@try { myPtr = malloc(...); }
@catch {}
@finally { free(myPtr); }
john.pavan
  • 910
  • 4
  • 6
  • it is c++ code. Im not sure where I should put this wrapping and what is the wrapping part. – some_id Mar 20 '13 at 11:37
  • C++ doesn't have a finally block. If there is error handling via exceptions, then you need to use the Resource Allocation Is Initialization (RAII) pattern. Otherwise when the stack is unwound free will not be called. It is good practice to use it whenever you have an allocation that requires another call to free the resource. http://en.wikipedia.org/wiki/Resource_acquisition_is_initialization – john.pavan Mar 20 '13 at 11:44
  • I get all kinds of errors for that code. Tilda flags an error, numShorts unidentified. – some_id Mar 20 '13 at 11:54
  • I dont get where I should put the code. For example in the objective C code, I can wrap the pointer in try, but I have two possible error points within the catch, and then I free the data pointer. – some_id Mar 20 '13 at 13:13
  • @john.pavan Are you sure it's that? The stack trace says the allocation is done with `new[]` and that it happens in a library function. Doesn't it? – yzt Mar 23 '13 at 04:57
1

Suggest that you start by simplifying, for example comment out (preferably using #if 0) all of the code except the malloc/free. Run the code and ensure no abandoned heap blocks. Then gradually re-introduce the remaining code and re-run until you hit the problem, then debug.

jarmod
  • 71,565
  • 16
  • 115
  • 122
  • I ended up removing the calls to the method that allocates the data and frees its. I still get the leak and it is now pointing to the bridging in this line err = ExtAudioFileOpenURL((__bridge CFURLRef)fileURL, &mExtAFRef); – some_id Mar 27 '13 at 00:05
0

Sorry to answer my own question, but after commenting out code back up the stack trace the actual issue was to do with the file not be disposed.

Calling ExtAudioFileDispose(audioFile); solved this hidden bug. Instruments was not entirely clear and marked mallocs as the leak. To be fair the mallocs where from data that was within the file referenced by the ExtAudioOpenFile method, not disposing the file reference left a leak.

some_id
  • 29,466
  • 62
  • 182
  • 304