Swift中的模糊低级致命错误
我有一个有序集的快速实现,我认为它是正确的(如果不是非常有效的话),因为NSOrderedSet不能与非ObjC结构一起工作。但是,当在多线程应用程序中使用该类时,我偶尔会遇到一个非常低级别的崩溃,它在控制台上只报告“致命错误”,并在调试器中显示:Swift中的模糊低级致命错误,swift,Swift,我有一个有序集的快速实现,我认为它是正确的(如果不是非常有效的话),因为NSOrderedSet不能与非ObjC结构一起工作。但是,当在多线程应用程序中使用该类时,我偶尔会遇到一个非常低级别的崩溃,它在控制台上只报告“致命错误”,并在调试器中显示: function signature specialization <preserving fragile attribute, Arg[1] = [Closure Propagated : reabstraction thunk helper
function signature specialization <preserving fragile attribute, Arg[1] =
[Closure Propagated : reabstraction thunk helper from @callee_owned
(@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) -> () to
@callee_owned (@unowned Swift.UnsafeBufferPointer<Swift.UInt8>) ->
(@out ()), Argument Types : [@callee_owned (@unowned
Swift.UnsafeBufferPointer<Swift.UInt8>) -> ()]> of generic
specialization <preserving fragile attribute, ()> of
Swift.StaticString.withUTF8Buffer <A>
((Swift.UnsafeBufferPointer<Swift.UInt8>) -> A) -> A
您能否提供(最终)导致错误的代码请注意,错误消息显示不正确。@MartinR-已使用调用上下文和整个调试器文本更新了问题。@MartinR-控制台仅显示“致命错误:2016-10-03 20:27:11.423135 XXX iPad[1513:905399]致命错误:(lldb)“哦,和self中的映射{$0}”。_set.map({$0})是不必要的。你可以直接调用sorted(),或者如果你想把它变成一个数组,那么我从你的语句中假设崩溃发生在应用程序中,而不是在测试工具中?如果是,您确定访问是线程安全的吗?
sort
方法是不可回避的,但是\u set
本身看起来并不能保证从不同线程访问和变异时线程安全。在这种情况下,您可能会遇到这样的情况:调用排序块时引用会消失或由于并发变异而更改。
import Foundation
fileprivate struct OrderedSetElementWrapper<T>: Hashable, Equatable where T: Hashable, T: Equatable {
let value: T
let index: Int
var hashValue: Int { return self.value.hashValue }
}
fileprivate func ==<T>(lhs: OrderedSetElementWrapper<T>, rhs: OrderedSetElementWrapper<T>) -> Bool {
return lhs.value == rhs.value
}
public struct OrderedSet<T> where T: Hashable, T: Equatable {
private var _set = Set<OrderedSetElementWrapper<T>>()
init() {}
init(array: [T]) { array.forEach { self.insert($0) } }
var array: [T] {
// ***** Error intermittently on next line ******
let sortedArray = self._set.sorted { $0.index < $1.index }
// **********************************************
let mapped = sortedArray.map { $0.value }
return mapped
//return self._set.sorted(by: { $0.index < $1.index }).map({ $0.value })
}
var set: Set<T> { return Set(self._set.map { $0.value } ) }
var count: Int { return self._set.count }
func contains(item: T) -> Bool { return self.set.contains(item) }
mutating func insert(_ item: T) {
self._set.insert(OrderedSetElementWrapper(value: item, index: self._set.count))
}
mutating func remove(_ item: T) {
var newSet = Set<OrderedSetElementWrapper<T>>()
for element in self._set {
if element.value != item {
newSet.insert(OrderedSetElementWrapper(value: element.value, index: newSet.count))
}
}
self._set = newSet
}
}
public class XXXItemGroupBase: XXXItemBase {
// ***************************************
// MARK: New properties
// ***************************************
private var _theItems = OrderedSet<XXXItemBase>()
// _theItems is used as a private backing store.
// Do NOT access it directly outside of the class -
// use self.components instead...
// ***************************************
// MARK: Overridden properties
// ***************************************
override public var components: [XXXItemBase] { // The public face of self._theItems
get { return self._theItems.array } // **** CRASH HERE ****
set { self._theItems = OrderedSet(array: newValue) }
}