Ошибка в получателе вычисляемых свойств

У меня есть в приложении iOS Swift 3 следующее вычисляемое свойство.

var countItems:[Int] {// Count the interesting items.
    var countResult = [Int]()
    for i in 0..<size {
        var count = 0
        for j in i*size..<(i+1)*size {
            if binaryArray?[j] == true {count += 1}
        }
        countResult.append(count)
    }
    return countResult
}

Он отлично работает в 99,9 процентах случаев. Но я получил сбой с этим сообщением:

* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0x16fc7bff0)
    frame #0: 0x000000018f2d95b8 libsystem_malloc.dylib`malloc_zone_malloc
    frame #1: 0x000000018f2dc56c libsystem_malloc.dylib`malloc + 32
    frame #2: 0x0000000100964048 libswiftCore.dylib`swift_slowAlloc + 12
    frame #3: 0x000000010096409c libswiftCore.dylib`_swift_allocObject_ + 28
    frame #4: 0x0000000100f6cd50 libswiftSwiftOnoneSupport.dylib`generic specialization <preserving fragile attribute, Swift._ArrayBuffer<Swift.Double> with Swift._ArrayBuffer<Swift.Double> : Swift._ArrayBufferProtocol in Swift> of (extension in Swift):Swift._ArrayBufferProtocol._forceCreateUniqueMutableBuffer (countForNewBuffer : Swift.Int, minNewCapacity : Swift.Int) -> Swift._ContiguousArrayBuffer<A.Element> with unmangled suffix "_merged" + 84
    frame #5: 0x0000000100f69d5c libswiftSwiftOnoneSupport.dylib`generic specialization <preserving fragile attribute, Swift.String.CharacterView> of Swift.Array._copyToNewBuffer (oldCount : Swift.Int) -> () with unmangled suffix "_merged" + 76
    frame #6: 0x0000000100f655bc libswiftSwiftOnoneSupport.dylib`generic specialization <preserving fragile attribute, Swift.UInt64> of Swift.Array.append (A) -> () with unmangled suffix "_merged" + 124
  * frame #7: 0x0000000100103078 MyApp`TheClass.countItems.getter(self=MyApp.TheClass @ 0x000000016fc7c260) at TheClass.swift:31
    frame #8: 0x0000000100138354 MyApp`TheClass.callingFunction(self=0x000000010201d930) -> Bool at TheClass.swift:2343

Интересно, есть ли проблема в самом вычисляемом свойстве (которого я не вижу) или что-то должно пойти не так снаружи. Если у кого есть инфа, буду очень рад. Заранее спасибо за любой соответствующий совет.

Для справки, вот еще один сбой с более коротким сообщением:

(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=2, address=0x16fc27fb0)
    frame #0: 0x00000001001567bc MyApp`TheClass.countItems.getter(self=MyApp.TheClass @ 0x000000016fc27fb0) at TheClass.swift:0
  * frame #1: 0x000000010018c2e4 MyApp`TheClass.callingFunction(self=0x000000010200c730) -> Bool at TheClass.swift:2348

person Michel    schedule 02.05.2017    source источник
comment
for j in i*size..<(i+1)*size для чего это?   -  person nayem    schedule 02.05.2017
comment
Возможно, вы пытаетесь получить доступ к элементу за пределами массива в этой строке: if binaryArray?[j] == true {count += 1}   -  person Jitendra Solanki    schedule 02.05.2017
comment
Что я могу сказать? Он здесь просто потому, что он мне нужен для вычисления того, что я хочу, а именно для подсчета; который затем добавляется в массив countResult, как вы можете видеть.   -  person Michel    schedule 02.05.2017
comment
Если бы я пытался получить доступ к элементу за пределами массива, вычисление не было бы выполнено миллионы раз до сбоя. Потому что я всегда обращаюсь к одним и тем же элементам. binaryArray создается один раз и только один раз. Только значения внутри могут измениться.   -  person Michel    schedule 02.05.2017


Ответы (2)


пожалуйста, попробуйте выполнить работу в фоновом потоке, так как вы, похоже, выполняете всю свою цифровую обработку в основном потоке, что не очень хорошо.

либо вы можете создать функцию, которая возвращает массив целочисленных элементов. который будет обрабатывать массив в фоновом потоке.

Поскольку я не знаю, что такое переменная binaryArray. вы можете пройти, если вам это нужно.

SWIFT 3.0:

func countItems(_ size : Int, completion: ([Int])) {
    let queue = DispatchQueue.global(qos: .background)
    queue.async {
        var countResult = [Int]()
        for i in 0..<size {
            var count = 0
            for j in i*size..<(i+1)*size {
                if self.binaryArray?[j] == true {count += 1}
            }
            countResult.append(count)
        }
        completion(countResult) 
    }
}
person Balaji Galave    schedule 02.05.2017
comment
В общем, хорошая идея для тяжелых вычислений, но я не думаю, что это решит его проблему :( - person Paulo Mattos; 02.05.2017
comment
Кроме того: при возврате массива countResult (т. е. при вызове completion) может быть разумнее сделать это в очереди DispatchQueue.main, чтобы быть в безопасности. - person Paulo Mattos; 02.05.2017
comment
Да. Вы можете вызвать блок завершения через основную очередь - person Balaji Galave; 03.05.2017
comment
Спасибо за предложения. Но, в конце концов, это была проблема, выходящая за рамки этого вычисления свойства. - person Michel; 04.05.2017
comment
Привет, @Michel, в чем была проблема помимо вычисления этого свойства? - person William Grand; 04.10.2017
comment
Это было давно и я точно не помню. Но когда я осознал свою ошибку, я понял, что на самом деле это не было связано с вопросом. С вычисляемым свойством проблем не было. - person Michel; 08.10.2017

Первая трассировка стека явно находится внутри метода Array.append с вызовом malloc вверху. Таким образом, вы можете столкнуться с внутренней ошибкой в ​​​​реализации Swift Array, возможно, в коде управления динамической памятью.

Предполагая, что это так, попробуйте выделить необходимую емкость массива один раз перед запуском алгоритма:

var countResult = [Int]()
countResult.reserveCapacity(size)

Если вы добавляете известное количество элементов в массив, используйте reserveCapacity, чтобы избежать многократного перераспределения. Этот метод гарантирует, что массив имеет уникальное, изменяемое, непрерывное хранилище с пространством, выделенным как минимум для запрошенного количества элементов.

В качестве бонуса вы также можете получить хороший прирост производительности для больших значений size :)

person Paulo Mattos    schedule 02.05.2017