我有一个com.springsource.org.aopalliance-1.0.0.jar
错误,一直出现,我需要一些帮助。我相信我已经设法确定了错误指针的来源,但我对如何修复它感到茫然。
显然swift编译器为我的一个类选择了错误的初始化程序。根据Instruments,有时当初始化类EXC_BAD_ACCESS(code=2 ...)
时,它会调用Description
的初始值设定项。不是所有的时间,有时候。无论编译器是设置为-Onone还是-O整个模块优化,它都会执行此操作。
这是两个类的样子:
LyricBlock
如您所见,class LyricBlock: Node, LeftDelimited, RightDelimited {
var leftDelimiter: Delimiter
var rigthDelimiter: Delimiter
init(start: Int, body: Range<Int>, end: Int) {
self.leftDelimiter = Delimiter(range: start..<body.lowerBound)
self.rightDelimiter = Delimiter(range: body.upperBound..<end)
super.init(range: body)
}
}
class Description: Node, LeftDelimited, RightDelimited {
var leftDelimiter: Delimiter
var leftDelimiter: Delimiter
init(start: Int, body: Range<Int>, end: Int) {
self.leftDelimiter = Delimiter(range: start..<body.lowerBound)
self.rightDelimiter = Delimiter(range: body.upperBound..<end)
super.init(range: body)
}
}
和LyricBlock
继承自Description
基类并共享一些协议,但除此之外它们彼此无关。
一些可能相关的代码:
Node
作为旁注,我想知道我是否可能遇到类签名的错误问题,并尝试使用class Node {
weak var parent: Node?
var next: Node?
var firstChild: Node?
weak var lastChild: Node?
let offset: Int
internal(set) var length: Int
init(range: Range<Int>) {
self.offset = range.lowerBound
self.length = range.upperBound - range.lowerBound
}
func addChild(_ child: Node) {
if firstChild == nil {
firstChild = child
} else {
lastChild?.next = child
}
lastChild = child
child.parent = self
}
}
class Parser {
// ...
func processLine(in buffer: Buffer) {
// Parse the current line as a block node.
var block = blockForLine(in: buffer)
// Try to find an appropriate container node. If none can be found, block will be replaced with Description.
let container = appropriateContainer(for: &block, in: buffer)
container.addChild(block)
// Edge case to parse first-line lyrics
if let cueBlock = block as? CueBlock {
if let lyricBlock = scanForLyric(in: buffer, at: cueBlock.direction.range.lowerBound) {
let lyricContainer = LyricContainer(range: lyricBlock.range.lowerBound..<endOfLineCharNumber)
lyricContainer.addChild(lyricBlock)
cueBlock.replaceDirection(with: lyricContainer)
parseInlines(for: lyricBlock, in: buffer)
}
}
// Parse inlines as appropriate
switch block {
case is FacsimileBlock, is Description, is LyricBlock:
parseInlines(for: block, in: buffer)
// ...
}
}
func blockForLine(in buffer: Buffer) -> Node {
let whitespace = buffer.scanForFirstNonspace(at: charNumber, limit: endOfLineCharNumber)
// ...
let endWhitespace = buffer.scanBackwardForFirstNonspace(at: endOfLineCharNumber, limit: wc)
let description = Description(start: charNumber, body: whitespace..< endWhitespace, end: endOfLineCharNumber)
return description
}
func appropriateContainer(for block: inout Node, in buffer: Buffer) -> Node {
switch block {
// These block types can only ever be level-1
case is Header, is Description, is EndBlock, is HorizontalBreak:
return root
// ...
case is LyricBlock:
guard let cueContainer = root.lastChild as? CueContainer else { break }
guard let cueBlock = cueContainer.lastChild as? CueBlock else { break }
guard let direction = cueBlock.direction as? LyricContainer else { break }
direction.extendLengthToInclude(node: block)
cueBlock.extendLengthToInclude(node: direction)
cueContainer.extendLengthToInclude(node: cueBlock)
return direction
default:
break
}
let whitespace = buffer.scanForFirstNonspace(at: charNumber, limit: endOfLineCharNumber)
let endWhitespace = buffer.scanBackwardForFirstNonspace(at: endOfLineCharNumber, limit: wc)
// Invalid syntax, time to fail gracefully
block = Description(start: charNumber, body: whitespace..< endWhitespace, end: endOfLineCharNumber)
return root
}
func parseInlines(for stream: Node, in buffer: Buffer) {
// ... scans buffer for inlines and enques them in queue
while let next = queue.dequeue() {
let nextRange = next.rangeIncludingMarkers
if nextRange.lowerBound > j {
let lit = Literal(range: j..<nextRange.lowerBound)
stream.addChild(lit)
}
stream.addChild(next)
j = nextRange.upperBound
}
if j < endOfLineCharNumber {
let lit = Literal(range: j..<nodeRange.upperBound)
stream.addChild(lit)
}
}
// ...
}
的{{1}}和rightDelimiter
属性而不是使用协议。这导致编译器调用我的leftDelimiter
初始值设定项。我不知道这证明了什么。坦率地说,我很茫然。帮助
答案 0 :(得分:0)
经过一些修修补补后,我能够至少部分解决这个问题。
事实证明,无论出于何种原因,ARC都会在超过一定规模的链接列表上疯狂。我能够通过在新项目中创建一个通用链表来确认这一点,然后慢慢地用更长的列表来测试它。
class LLNode<T> {
var value: T?
var next: LLNode<T>?
weak var previous: LLNode<T>?
}
class LList<T> {
var head: LLNode<T>
var tail: LLNode<T>
// boring old linked list implementation
}
let list = List<Int>()
for i in 0..<10000 {
list.append(i)
}
果然,在大约10,000个节点之后,我开始在通用列表上再次获得EXC_BAD_ACCESS,但仅在list
被取消初始化时。这与我上面的解析器完全匹配的行为相匹配。由于我的代码使用链接列表来模拟树中的子项(引用计数的两个维度!),因此ARC必须自己解决所有这些引用 - 并且失败。为什么它会像那样崩溃仍然超出我的解释能力,但这至少解释了崩溃的源。
为了确认,我在C中创建了另一个链表,并在其周围创建了一个Swift包装器,所有垃圾收集都在C中实现。
import liblist
class List<T> {
var list: UnsafeMutablePointer<llist>
// Swift interface with list
deinit {
list_free(list)
}
}
包装器能够处理我投掷的每个尺寸 - 多达500,000个节点,此时我感到满意并停止测试。
如果有人对我用来解决这个问题的完整代码感兴趣,我在https://github.com/dmcarth/List创建了一个Swift包