TheAmazingAudioEngine / TheAmazingAudioEngine2

The Amazing Audio Engine is a sophisticated framework for iOS audio applications, built so you don't have to.
http://theamazingaudioengine.com/doc2
Other
544 stars 87 forks source link

Odd behavior when accessing out-of-bounds index for AEArray #37

Closed manderson-productions closed 8 years ago

manderson-productions commented 8 years ago

I noticed some odd behavior when using an AEArray inside a renderer.block today (which may be intentional actually). Let me know if this is actually desired behavior though, if not, it should be a pretty easy fix that I can throw into a PR.

1) Create an AEArray of NSNumbers of type AESeconds for demonstration purposes

self.durationArray = [[AEArray alloc] init]; NSMutableArray *intervalArray = [[NSMutableArray alloc] init]; for (int i = 0; i < 3; i++) { [intervalArray addObject:@((AESeconds)i)]; } [self.durationArray updateWithContentsOfArray:intervalArray];

2) Now if you use a subscript to access something out of bounds of the array, I would expect an exception to be thrown. Instead, it appears that the thread just gets locked and the execution stops at the line in which the index is being accessed out of bounds. For instance, if I put a breakpoint on the following line, which is out of bounds of the array, the thread does not continue past that line of execution:

AESeconds seconds = [self.durationArray[6] doubleValue];

Is this expected or should there be an exception thrown? Maybe I'm just getting odd behavior since I have only tested this inside the renderer.block which is happening on the core audio thread, so you may have some insight into what is going on. Thanks!

michaeltyson commented 8 years ago

Wow that's weird - nope, that's most definitely a bug. Weirdly, though, that code's interacting only with the underlying NSArray from what I can see, because AEArray just calls straight down to it in that case.

If you're doing that stuff on the render thread, that is not quite the right usage pattern, though: AEArray is designed so you write to it on the main thread via Objective-C, and then read from it on the Core Audio thread in C only, because using Objective-C on the audio thread is a big no-no. So if you were wanting to keep an array of numbers, for instance, then you'd want to provide a mapping block in the AEArray initializer which takes an NSNumber and returns a pointer to an AESeconds. Then use the C API to access that on the audio thread.

manderson-productions commented 8 years ago

Ah sorry I wasn't very clear: I am doing all the initialization/ updating of the AEArray on the main thread in my audio effect subclass that keeps a reference to the array. I am only reading from the array on the render thread...you're correct though that the problem is that I wasn't using the token to access the array index via the C api as I should.

Accessing an index out of bounds now crashes as expected as long as I use the correct accessor:

AEArrayToken token = AEArrayGetToken(self.durationArray); AEArrayGetItem(token, 6);

Thanks for pointing out the (should have been) obvious!

lijon commented 8 years ago

Just a quick note. This is obj-c and no good in audio thread: self.durationArray Use direct access to the instance var instead, THIS->_durationArray or similar.

/Jonatan

24 Sep 2016 kl. 18:08 skrev manderson notifications@github.com:

self.durationArray

michaeltyson commented 8 years ago

You can detect these kind of mistakes by enabling Realtime Watchdog. It's built into TAAE, just look for AERealtimeWatchdog

Sent from my iPhone

On 25 Sep. 2016, at 02:19, Jonatan Liljedahl notifications@github.com wrote:

Just a quick note. This is obj-c and no good in audio thread: self.durationArray Use direct access to the instance var instead, THIS->_durationArray or similar.

/Jonatan

24 Sep 2016 kl. 18:08 skrev manderson notifications@github.com:

self.durationArray — You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.