跳到主要内容
知仓学习社ZHICANG

ios-memgraph-analysis

Use when capturing or analyzing an iOS .memgraph, especially when the task mentions a memory leak, heap growth, persistent memory increase, ownershi…

执行命令读文件严重 0 · 高危 2dpearson2699/swift-ios-skills

它会碰到什么

扫了多少5 个文本文件,36 KB
它会碰到什么执行命令读文件
命中总数3 处
命中统计严重 0 · 高 2 · 中 1 · 低 0
逐条看命中(2 条严重或高危)
  • scripts/capture_sim_memgraph.py:18exec-spawn
    return subprocess.run(command, text=True, capture_output=True, check=False)
  • scripts/summarize_memgraph.py:56exec-spawn
    result = subprocess.run(

这一栏是扫描器报的事实,不是结论。命中多不等于有毒(安全工具、规则库、示例脚本本来就会包含危险写法),命中少也不等于干净。它和你手上的凭据、文件、网络有什么关系,需要你自己看。

技能内容

iOS Memgraph Analysis

Use memory graphs to prove why memory survives a defined lifetime boundary.

Separate unreachable leaks from reachable growth, preserve raw tool output, and

verify the same app-owned type and ownership path after a fix.

Contents

  • [Boundary](#boundary)
  • [Evidence Model](#evidence-model)
  • [Workflow](#workflow)
  • [Ownership Decisions](#ownership-decisions)
  • [Common Mistakes](#common-mistakes)
  • [Review Checklist](#review-checklist)
  • [References](#references)

Boundary

This skill owns .memgraph capture and command-line ownership/growth analysis.

Use the Memory Graph Debugger or Instruments when their interactive graph and

allocation timeline are the primary task. Use source review for a suspected

closure capture only after runtime evidence identifies the lifetime or path.

Evidence Model

Do not collapse these conditions:

  • Unreachable leak: allocated memory no longer has a path from a live root.

An isolated strong cycle can be unreachable and still consume memory.

  • Reachable but abandoned state: a live root still retains objects the user

flow no longer needs. leaks may correctly report zero.

  • Expected cache or pool: memory survives intentionally and must be judged by

its bound, eviction behavior, and pressure response.

  • Heap regression or fragmentation: footprint grows because more/larger

allocations persist or dirty pages are poorly utilized, without a leak.

Apple's leak scanner uses conservative pointer discovery and incomplete type

metadata. Counts can fluctuate, and a zero result does not prove the absence of

an ownership bug. Strong evidence identifies the expected lifetime, an

app-owned type or allocation, and a credible path or isolated reproduction.

Workflow

1. Define the lifetime before capturing

Name the object that should disappear and the event that ends its useful life.

For example: EditorViewModel should deinitialize after dismissing the editor

and completing pending save work.

Record one deterministic sequence:

  1. launch or restore a known state;
  2. take an optional baseline graph;
  3. perform the feature flow;
  4. cross the expected release boundary;
  5. wait for legitimate asynchronous cleanup;
  6. take the post-flow graph.

Keep build, simulator/device, data, Malloc Stack Logging setting, and repetition

count stable. Malloc Stack Logging adds valuable allocation backtraces but also

overhead; compare only runs with the same setting.

2. Capture a graph without guessing the process

Xcode can export a graph from the Memory Graph Debugger. For a running Simulator

app, use the helper from this skill:

mkdir -p /tmp/myapp-memory
mkdir /tmp/myapp-memory/run-01
python3 scripts/capture_sim_memgraph.py \
  --bundle-id com.example.MyApp \
  --output-dir /tmp/myapp-memory/run-01 \
  --pretty > /tmp/myapp-memory/run-01/capture.json

The per-run mkdir must fail if the capture directory already exists. Use a

new run name rather than mixing stale evidence with a retry.

Pass --udid when more than one Simulator is booted. The helper accepts only

one exact launchd label and PID; zero or multiple matches are errors. It runs the

host leaks --outputGraph command, retains stdout/stderr, and writes a manifest.

Do not replace this with pgrep | head -1 or a substring match.

Capturing suspends the process. Do not use capture latency as performance data.

3. Preserve raw output and build a bounded summary

MEMGRAPH=$(jq -er \
  'select(.status == "captured") | .memgraph | select(type == "string" and length > 0)' \
  /tmp/myapp-memory/run-01/capture.json)
test -s "$MEMGRAPH"
python3 scripts/summarize_memgraph.py \
  "$MEMGRAPH" \
  --artifact-dir /tmp/myapp-memory/run-01/analysis-raw \
  --app-image 'MyApp|MyFeatureKit' \
  --trace-limit 3 --group-by-type --pretty \
  > /tmp/myapp-memory/run-01/analysis.json

Read the exact graph path from the preserved capture report; do not guess a

timestamped filename. The helper creates a dedicated raw-artifact directory,

refuses to reuse it, runs leaks --list, and parses only a conservative subset

of its text. --app-image marks candidate rows; it does not prove ownership.

--trace-limit runs bounded

leaks --traceTree=<address> queries. Add --reference-tree when aggregate

root paths are more useful than individual leaked addresses. With

--group-by-type, that reference-tree query is grouped in the same invocation.

Exit statuses 0 and 1 from leaks remain analyzable; a primary status above 1

fails the summary, while optional-query failures are preserved and warned as

unusable without discarding a valid primary summary.

Apple does not publish these text formats as stable machine schemas. Treat

parse warnings as a reason to inspect the raw artifacts, not to loosen the

parser until it emits a desired answer.

4. Find the first actionable app-owned edge

Start with an app-owned leaked type or allocation stack. Inspect:

  • the leak's object graph and Malloc Stack Logging backtrace, when present;
  • a bounded --traceTree=<address> for objects that reference one address;
  • --groupByType to compress repeated types and reveal a retained payload;
  • --referenceTree for a top-down view when the responsible address is unclear;
  • source code for the first strong edge controlled by the app.

An unreachable self-cycle may have no live root in traceTree. Use the grouped

leak graph plus source verification or reduce the behavior to an isolated

reproduction. Never invent a root path that the graph does not contain.

5. Investigate growth when leaks is empty

Use matching baseline and post-flow graphs, locate the growing region, compare

object types, then trace a suspicious address back to an app-owned edge. The

evidence goal is persistent reachable growth across the same lifetime—not a

lower RSS value or a single large snapshot. Load

[reachable-growth.md](references/reachable-growth.md) only for this empty-leak

branch; it contains the ordered vmmap, heap, leaks, and malloc_history

queries and their logging-dependent alternatives.

6. Fix and verify the same lifetime

Prefer the narrowest ownership correction: break the unintended strong edge,

cancel work that owns the object, remove an observer, bound/evict a cache, or

release a large buffer after its last use. Use weak when the reference may

legitimately become nil; use unowned only with a proven lifetime guarantee.

Repeat the identical flow. A fix is supported when the same app-owned type/path

disappears or the pre/post growth attributable to it is removed across repeated

runs. Lower RSS, a smaller graph file, or a lower aggregate leak count alone is

not proof.

Ownership Decisions

| Evidence | Next action |

|---|---|

| App type in a root cycle | Inspect both strong edges and allocation stack. |

| No root for a leaked address | Inspect grouped cycle evidence and isolate the flow. |

| Live root retains dismissed feature state | Follow the path to the first app-owned edge. |

| Zero leaks but repeated malloc growth | Diff baseline/post heap objects. |

| Framework object dominates | Find the app-created owner, input, or call frequency. |

| Growth stabilizes at a documented bound | Test eviction/pressure behavior before changing it. |

Common Mistakes

  • Declaring the app leak-free because leaks returned zero once.
  • Selecting the first PID or Simulator from an ambiguous list.
  • Enabling Malloc Stack Logging in only one side of a comparison.
  • Treating a parser's best-effort type column as an API guarantee.
  • Pasting enormous reference trees into a report without finding an app edge.
  • Fixing every closure with [weak self] without reasoning about lifetime.
  • Claiming success from graph size, RSS, or total-count changes without proving the target lifetime and ownership path.

Review Checklist

  • [ ] The object and expected release boundary are explicit.
  • [ ] Baseline and post-flow graphs use the same build, runtime target, data

state, deterministic flow, cleanup wait, repetitions, and Malloc Stack

Logging setting.

  • [ ] Simulator, bundle identifier, process label, and PID are unambiguous.
  • [ ] Original graph and raw command outputs are preserved.
  • [ ] Current installed-tool help confirms version-sensitive command shapes.
  • [ ] Leak, reachable growth, expected cache, and fragmentation are separated.
  • [ ] The finding names an app-owned type/allocation and credible path.
  • [ ] Missing type metadata or conservative-scanner limits are disclosed.
  • [ ] The fix changes one ownership/lifetime cause.
  • [ ] Verification repeats the same flow and evidence query.

References

  • [Reachable growth when leaks is empty](references/reachable-growth.md) —

matched-graph comparison and address-to-owner workflow

想直接用这个技能?

本站把开放许可(MIT / Apache 等)的技能按仓库打包整理到网盘,点一下转存到你自己的网盘,不用一个个从 GitHub 拉。许可未声明的技能只给原始仓库链接,不打包。