From 15b7df0982927469acbafec1cfc2a64769d4929b Mon Sep 17 00:00:00 2001 From: ShikiSuen Date: Thu, 2 Mar 2023 20:27:59 +0800 Subject: [PATCH] Fix memory leak with Vertex. (#96) --- Sources/Megrez/2_Walker.swift | 14 +++++++++++--- Sources/Megrez/5_Vertex.swift | 12 +++++++++++- 2 files changed, 22 insertions(+), 4 deletions(-) diff --git a/Sources/Megrez/2_Walker.swift b/Sources/Megrez/2_Walker.swift index bc34c60..8553fdd 100644 --- a/Sources/Megrez/2_Walker.swift +++ b/Sources/Megrez/2_Walker.swift @@ -32,6 +32,7 @@ public extension Megrez.Compositor { } let terminal = Vertex(node: .init(keyArray: ["_TERMINAL_"])) + var root = Vertex(node: .init(keyArray: ["_ROOT_"])) for (i, vertexSpan) in vertexSpans.enumerated() { for vertex in vertexSpan { @@ -46,11 +47,10 @@ public extension Megrez.Compositor { } } - let root = Vertex(node: .init(keyArray: ["_ROOT_"])) root.distance = 0 root.edges.append(contentsOf: vertexSpans[0]) - var ordered: [Vertex] = topologicalSort(root: root) + var ordered = topologicalSort(root: &root) for (j, neta) in ordered.reversed().enumerated() { for (k, _) in neta.edges.enumerated() { relax(u: neta, v: &neta.edges[k]) @@ -58,15 +58,23 @@ public extension Megrez.Compositor { ordered[j] = neta } + var iterated = terminal var walked = [Node]() var totalLengthOfKeys = 0 - var iterated = terminal + while let itPrev = iterated.prev { walked.append(itPrev.node) iterated = itPrev totalLengthOfKeys += iterated.node.spanLength } + // 清理內容,否則會有記憶體洩漏。 + ordered.removeAll() + vertexSpans.removeAll() + iterated.destroy() + root.destroy() + terminal.destroy() + guard totalLengthOfKeys == keys.count else { print("!!! ERROR A") return (result, false) diff --git a/Sources/Megrez/5_Vertex.swift b/Sources/Megrez/5_Vertex.swift index 3a64b31..6072d33 100644 --- a/Sources/Megrez/5_Vertex.swift +++ b/Sources/Megrez/5_Vertex.swift @@ -29,6 +29,16 @@ extension Megrez.Compositor { public init(node: Node) { self.node = node } + + /// 讓一個 Vertex 順藤摸瓜地將自己的所有的連帶的 Vertex 都摧毀,再摧毀自己。 + /// 此過程必須在一套 Vertex 全部使用完畢之後執行一次,可防止記憶體洩漏。 + public func destroy() { + while prev?.prev != nil { prev?.destroy() } + prev = nil + edges.forEach { $0.destroy() } + edges.removeAll() + node = .init() + } } /// 卸勁函式。 @@ -67,7 +77,7 @@ extension Megrez.Compositor { /// 至於其遞迴版本,則類似於 Cormen 在 2001 年的著作「Introduction to Algorithms」當中的樣子。 /// - Parameter root: 根頂點。 /// - Returns: 排序結果(頂點陣列)。 - func topologicalSort(root: Vertex) -> [Vertex] { + func topologicalSort(root: inout Vertex) -> [Vertex] { class State { var iterIndex: Int let vertex: Vertex