Post

Replies

Boosts

Views

Activity

Bad access with a fixed size array and index in range
Hi, first post here, I've also raised this question on stack overflow. I'm getting crashes from a fixed size array even though I thought I'd protected the index from going out of range. The array updates in a loop, like a ring buffer. This crashes reliably when the array size >638 but I've not managed to get it to crash with fewer elements. I'm wondering whether this is compiler 'optimisation'... and what to do if it is. Any ideas gratefully received. struct ZeroCrossing { //The integer index of the second sample (cross over is between two samples) var index: UInt //The highest amplitude peak (negative or positive) between this and the previous crossing let previousPeak: Float //The interpolated crossover point between the two sample indices let indexWithOffset: Double } class CrossingBuffer { private var array: [ZeroCrossing] private let size: Int private var nextWriteIndex = 0 private var full: Bool { nextWriteIndex >= size } init(size: Int) { self.size = size array = [ZeroCrossing](repeating: ZeroCrossing(index: 0, previousPeak: 0, indexWithOffset: 0), count: size) array.reserveCapacity(size) } public func write(_ val: ZeroCrossing) { array[nextWriteIndex % size] = val nextWriteIndex += 1 } public func getAfterIndex(_ refIndex: Double) -> [ZeroCrossing]? { if !full { return nil } var subArray = [ZeroCrossing]() let lastElementIndex = nextWriteIndex - 1 for i in 0...size - 1 { // CRASHES ON NEXT LINE !!! let thisCrossing = array[(lastElementIndex - i) % size] if thisCrossing.indexWithOffset > refIndex { subArray.append(thisCrossing) } else { break } } return subArray.reversed() } public func reset() { array = [ZeroCrossing](repeating: ZeroCrossing(index: 0, previousPeak: 0, indexWithOffset: 0), count: size) nextWriteIndex = 0 } } The backtrace ends with the following * thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x1016dc008) frame #0: 0x000000018bf5c090 libswiftCore.dylib`swift_retain + 60 frame #1: 0x000000018bf9c704 libswiftCore.dylib`swift_bridgeObjectRetain + 56 * frame #2: 0x0000000100838e50 CrossingBuffer.getAfterIndex(refIndex=431975.76999999583, self=0x00000002800a86f0) at CrossingBuffer.swift:97:31 frame #3: 0x00000001007cd704 correlate(self=0x000000010130e5c0) at PitchEngine.swift:146:52 frame #4: 0x00000001007a155c correlate(self=0x0000000283b91200) at TunerEngine.swift:57:39 frame #5: 0x00000001007a1bd8 @objc correlate() at <compiler-generated>:0 But what's strange is that I can access the element from the debug console using the same index reference as the line it crashed on: (lldb) print (lastElementIndex - i) % size (Int) $R4 = 838 (lldb) print array.count (Int) $R5 = 1000 (lldb) print array[(lastElementIndex - i) % size] (ZeroCrossing) $R6 = (index = 438691, previousPeak = 0.0251232013, indexWithOffset = 438690.12000000477) The following code should trigger the crash, the mic needs to pick up some noise for the array to populate. import Foundation import AVKit final class AudioTap { private var audioEngine = AVAudioEngine() private var windowIndex: UInt = 0 private var lastPeak: Float = 0 private var lastSample: Sample? public var minPeakSize: Float = 0.005 // Size of crossingBuffer changes crashing behavior private var crossingBuffer = CrossingBuffer(size: 2000) private var lastSeekIndex: Double = 0.0 private var timer: Timer? init() { installTunerTap() audioEngine.prepare() do { try audioEngine.start() } catch let error as NSError { print("AVAudioEngine error on start: \(error.domain), \(error)") } timer = Timer.scheduledTimer( timeInterval: 0.01, target: self, selector: #selector(getNext), userInfo: nil, repeats: true) } private func installTunerTap() { let inputNode = audioEngine.inputNode inputNode.installTap( onBus: 0, bufferSize: 1000, format: nil, block: { buffer, when in let sampleCount = Int(buffer.frameLength) var sampleIndex = 0 while (sampleIndex < sampleCount) { if let val = buffer.floatChannelData?.pointee[sampleIndex]{ let sample = Sample(index: self.windowIndex, val: val) self.update(sample: sample) } self.windowIndex += 1 sampleIndex += 1 } }) } private func update(sample: Sample) { lastPeak = abs(sample.val) > abs(lastPeak) ? sample.val : lastPeak if let last = lastSample { if last.val * sample.val < 0 && abs(lastPeak) > minPeakSize { // this is a zero crossing let offset = Double(sample.index) + Double(round((sample.val/(last.val - sample.val)) * 100) / 100) let crossing = ZeroCrossing( index: sample.index, previousPeak: lastPeak, indexWithOffset: offset ) crossingBuffer.write(crossing) lastPeak = 0 } } lastSample = sample } @objc func getNext() { if let arr = crossingBuffer.getAfterIndex(lastSeekIndex) { if let s = arr.last { lastSeekIndex = s.indexWithOffset } } } }
5
0
1.5k
Jun ’22
CloudKit Crashing after App Release
I have an app that uses cloudKit in the app store. I have now realised that I should have deployed the schema to production before releasing the app. I reset the environment and now the app crashes on startup. Is there a way back from this? Any suggestions would be greatly appreciated as I'm no longer able to preview or install the app on a device.
1
0
512
Aug ’22