⚡ 站長快讀:核心重點
- 文章屬性:教學實戰(工具深度)
- 適用系統:Windows 10 1607+ / Windows 11(x64、ARM64);TTD.exe 另支援 Windows Server 2016–2025
- 難易度 / 耗時:⭐⭐⭐ / 約 40 分鐘
- 核心結論:傾印檔給你死亡瞬間的快照,Time Travel Debugging(TTD)給你整段死亡過程——差別不在誰比較強,而在你缺的是「狀態」還是「過程」。
- 適用對象:應用程式偶發當機、重現一次要等半天,已會看
!analyze -v卻苦於「快照看不到之前發生什麼」的人
📌 快速答案
一句話答案:Time Travel Debugging 是 WinDbg 內建的使用者模式錄製回放功能,先用 TTD 把程式執行過程錄成
.run追蹤檔,再於 WinDbg 用g-、p-、!tt往回走,並以dx查詢例外與 API 呼叫定位根因。
🧰 開始前的準備
- 系統需求:依官方 WinDbg 安裝頁,WinDbg 支援 Windows 11 全版本與 Windows 10 1607 以上,處理器架構限 x64 與 ARM64;若要用命令列錄製器,微軟官方文件另載明 Windows Server 2016、2019、2022、2025 皆支援 TTD.exe
- 權限需求:必須是系統管理員。官方明確要求以提升權限執行偵錯工具——在開始功能表對 WinDbg 圖示按右鍵 → 更多 → 以系統管理員身分執行;而且安裝 WinDbg 的那個帳戶本身就要有管理員權限,用一般帳戶裝完再提權,依然會跳「WinDbg must be run elevated to support Time Travel Debugging」
- 需要工具:WinDbg(TTD 已整合在裡面,不必另外裝);只想在沒有偵錯器的機器上錄製,則單獨安裝 TTD 命令列錄製器
- 磁碟空間:官方直說追蹤檔「can get big」——錄幾分鐘就可能長到數 GB,而且 TTD 刻意不設追蹤檔大小上限;另外索引檔
.idx通常是追蹤檔的兩倍大(官方值),所以站長的實務估法是照「追蹤檔 × 3」抓空間(此估法為站長推導,非官方數字) - 預計耗時:約 40 分鐘(含首次安裝與符號設定)
- 難度門檻:看得懂 WinDbg 指令列、知道什麼是模組與執行緒。還沒把符號路徑設好的人請先去設——TTD 的查詢功能沒有符號會直接退化成一堆
UnknownOrMissingSymbols,設定方法見〈WinDbg Preview 安裝與符號路徑設定完整教學:為什麼你的當機分析報告一堆問號〉
🔍 為什麼你需要這個?
先講痛點。傾印檔分析走到某個程度,一定會撞到同一堵牆:!analyze -v 告訴你的是「死在哪一行」,不是「為什麼會走到這一行」。堆疊上那個空指標是從哪裡來的?那個被釋放兩次的物件,第一次是誰放的?這些答案不在快照裡,因為快照只有崩潰那一瞬間的記憶體狀態,之前十萬條指令的執行歷史全部沒有被保留。
傳統解法是「加 log、重現、再看一次」,但偶發性 bug 可能兩天才復現一次,而 log 只覆蓋你猜得到的路徑。TTD 把這件事整個翻轉:先把執行過程完整錄起來,事後再決定要看哪裡。錄好之後,你可以在追蹤檔裡設中斷點、再往「過去」跑到它被命中的地方——這是實時偵錯做不到的,因為等你發現該設中斷點時,現場早就過去了。微軟官方也把這列為 TTD 相對於傾印檔的優勢:傾印檔常常「錯過導致最終失敗的狀態與執行路徑」。
本文和站內既有的 WinDbg 系列有三個明顯不同的切入角度,先在這裡亮出來:
- 定位法,不是功能表:同樣是除錯,傾印檔、實時偵錯、TTD 分別解決不同形狀的問題。文中會以官方的除錯手段比較表為基礎、由站長整理成一張可用的分工表,給你什麼時候該選哪個的判準。
- 開銷是可以調的:多數人聽到「10x–20x 慢」就打退堂鼓,但官方同一份文件也寫著「多數情況下沒必要錄整個行程」——
-module、-ring、-recordmode Manual三個旋鈕就是為此存在,本文會逐一說明。 - 錄完只是一半,查得到才算數:TTD 真正的殺手鐧是
dx+ LINQ 查詢。與其手動一步步p-往回退,不如直接查「這段追蹤裡所有的例外」「GetLastError回傳非零的所有時間點」,一句話跳到現場。
🛠️ 實戰步驟
⚠️ 錄製前務必知道的三件事(官方明載,不是站長加戲)
1. 追蹤檔可能含個資與敏感資訊:錄製會抓記憶體內容,可能包含檔案路徑、登錄、記憶體或檔案內容,實際內容取決於被錄製行程當下在做什麼。把
.run丟給同事或附在工單前,請先想清楚裡面錄到了什麼。2. TTD 附著之後無法自行卸離:官方原文是「Once TTD attaches to a process, it can’t remove itself」——錄完請關閉該應用程式或結束該行程;若對象是系統關鍵行程,則需要重新開機才能脫離。
3. 這是侵入式技術:它會和防毒、應用程式虛擬化框架、資安軟體等同樣侵入式的東西打架,錄不起來時這是第一個要懷疑的方向。
步驟一:確認 TTD 跑得起來
TTD 已經整合在 WinDbg 裡,不需要另外安裝元件。先做三件事確認環境正常:
1. 以系統管理員身分開啟 WinDbg。 開始功能表 → 對 WinDbg 按右鍵 → 更多 → 以系統管理員身分執行。
2. 若跳出提權錯誤且你已經提權了,代表當初安裝 WinDbg 的帳戶沒有管理員權限——官方的處置是用有管理員權限的帳戶重新安裝 WinDbg,並用該帳戶錄製。
3. 先錄一個最簡單的東西當基準線。 官方疑難排解章節的建議:先確認 ping.exe 或 cmd.exe 這類單純行程能不能錄。能錄=問題在你的目標程式;連 ping.exe 都錄不起來=環境層級衝突,往防毒與資安軟體查。
步驟二:在 WinDbg 介面錄一段追蹤
官方提供兩條錄製路徑,差別在於「程式是你啟動的」還是「程式已經在跑」。
路徑 A:啟動並錄製(Launch executable (advanced))
- WinDbg → File → Start debugging → Launch executable (advanced)
- 填入或瀏覽選擇要錄製的使用者模式執行檔
- 勾選 Record with Time Travel Debugging
- 想指定追蹤檔位置,選 Configure and Record
- 想省空間,勾「Record subset of execution」:在文字框輸入模組名稱即可限定錄製範圍。只錄記事本就填
notepad.exe;要連kernelbase.dll一起錄,就填notepad.exe,kernelbase.dll - 按 OK 啟動程式並開始錄製
路徑 B:附著到執行中的行程(Attach to process)
- WinDbg → File → Start debugging → Attach to process
- 選取目標使用者模式行程
- 勾選 Record Process with Time Travel Debugging
- 按 Attach 開始錄製
💡 為什麼要分兩條路? 服務、長時間執行的常駐程式、以及「已經進入異常狀態」的行程,你沒辦法用啟動參數重來一次,只能附著。另外官方特別註明:UWP 應用程式不支援「啟動並錄製」,但可以附著到已在執行的 UWP 應用程式來錄製。
錄製中的操作:這時候就是去把你要抓的問題重現出來——開那個會壞掉的檔案、按那顆會當掉的按鈕。錄製對話框上有兩顆按鈕:
- Stop and debug:停止錄製、建立追蹤檔,並直接開啟追蹤檔進入偵錯
- Cancel:停止錄製並建立追蹤檔,之後再自行開啟
⚠️ 官方註記:這兩個選項都會終止相關的行程。 「Cancel」不是「取消錄製」的意思,別被字面誤導。
另外一個好消息:如果程式直接崩潰了,追蹤檔一樣會被關閉並寫出磁碟——被錄製的應用程式終止時(不論正常結束或崩潰)追蹤檔都會完成。
步驟三:改用 TTD.exe 命令列錄製器
當你需要「在沒裝偵錯器的機器上錄」「錄開機就出事的程式」「把錄製包進自動化測試腳本」,就輪到命令列錄製器上場。
安裝:到官方下載頁 <https://aka.ms/ttd/download> 取得,按 *Install* 後會自動下載安裝,完成後 ttd 指令會被加入系統路徑。
驗證安裝是否成功,開一個新的命令提示字元:
ttd.exe -help錄製要用系統管理員身分的命令提示字元執行,這點和 WinDbg 一樣。官方提供三種模式:
| 模式 | 適用情境 | 官方舉的例子 |
|---|---|---|
-launch(預設) | 要用特定引數啟動新行程 | 錄製 ping.exe 這類命令列工具 |
-attach <PID> | 錄製已經在跑的行程 | 偵錯服務或長時間執行的應用程式 |
-monitor <Program> | 每次該程式啟動就自動錄 | 抓偶發問題或開機階段的問題 |
模式一:啟動並錄製。 -launch 是預設模式,可以省略;它也是唯一能傳引數給目標程式的模式:
TTD.exe -launch notepad.exeTTD.exe ping.exe msn.com模式二:附著到執行中的行程。 先用工作管理員或 TaskList 找出 PID,再:
TTD.exe -attach 21440 -out C:\TTD\MyTraceFile.run⚠️ -out 指定目錄時,該目錄必須事先存在(上例的 C:\TTD);指定檔名時,該檔名則必須不存在。
模式三:監看啟動。 這是抓「一啟動就出事」最有效的一招——它會錄下目標程式當下與未來的每一個實例,直到你按 Ctrl+C 或系統重開:
TTD.exe -out C:\TTD\ -monitor notepad.exe-monitor 有三個官方列出的好處:①用平常的方式啟動目標程式即可,不必湊出它的命令列;②目標程式以原本的權限執行(直接用 ttd.exe 啟動會變成提權執行,可能改變程式行為);③適合自動化。它可以指定多次以監看多個程式;搭配 -cmdLineFilter "specialfile.txt" 還能只在命令列含特定字串時才錄。
步驟四:壓低錄製開銷(多數人跳過、但最該做的一步)
官方對效能開銷的說法在兩份文件裡略有差異,兩個都照實引給你:總覽頁寫「典型錄製情境約有 10x–20x 的效能衝擊」,TTD.exe 命令列頁則寫「5x–20x 或更多,取決於應用程式與你選的錄製選項」。不論取哪個數字,結論一樣:別無腦錄整個行程。官方的原話是「In many cases recording the entire process is not necessary」。
三個旋鈕:
1. -module <module name>——只錄指定模組與它呼叫的程式碼。
TTD.exe -out C:\TTD\ -module mymodule.dll -launch myapp.exe它的運作方式很聰明:目標行程以全速執行,直到指定模組裡的程式碼被執行,TTD 才開始錄;執行離開該模組時就關掉錄製、回到全速。官方也誠實說明代價——因為開關錄製本身很昂貴,指定模組呼叫其他模組時 TTD 會讓錄製繼續開著。這個選項可以指定多次。
2. -ring + -maxFile <MB>——環形緩衝區,只留最後一段。
TTD.exe -out C:\TTD\ -ring -maxFile 512 -attach 21440檔案不會超過 -maxFile 指定的大小,只保存塞得進去的最後那一段錄製。這對「跑很久才出事」的情境是救命稻草。官方數字:完整追蹤模式下 -maxFile 預設 1,024 GB、最小 1 MB;環形緩衝模式下預設 2,048 MB、最小 1 MB、最大 32,768 MB;32 位元行程的記憶體內環形緩衝預設為 256 MB。
3. -recordmode Manual——由程式自己決定何時開始錄。
預設是 Automatic:TTD 一注入目標行程就開始錄。若你的程式有接上 TTD 的行程內錄製 API,改用 Manual 就能讓它全速執行到程式自己呼叫 API 開始錄製為止。
💡 重點是:用這些選項錄出來的追蹤檔,偵錯體驗跟錄整個行程沒有差別。 官方明說,當你走到某個「錄製當時是關閉的」位置,追蹤裡的下一條指令就是錄製恢復後執行的第一條指令——不會有奇怪的斷裂。
其他常用旗標,一次列給你:
-noUI:關掉那個小小的錄製控制視窗,自動化情境用這個-accepteula:自動接受授權條款(自動化情境用;首次執行會要求你輸入 Y/N)-children:連目標建立的子行程一起錄,每個子行程各自產生一個追蹤檔-timestampFilename:檔名加上時間戳,例如ping_2023-06-17_103116.run(不加的話預設是ping01.run、ping02.run依序找沒用過的檔名)-stop <程序名 | PID | all>:停止指定的錄製-numVCpu <數量>:保留給錄製使用的虛擬 CPU 數,影響 TTD 加在目標行程上的記憶體開銷;預設 x64/ARM64 為 55、x86 為 32。官方警告:只有記憶體不足時才調低,調低會嚴重影響錄製效能;但若錄製失敗或.out顯示模擬時間為 0 秒,調它有機會讓錄製成功-cleanup:卸載行程監看驅動程式(用過-monitor之後的收尾動作)
步驟五:回放——在時間軸上前後移動
追蹤檔開起來之後,WinDbg 會自動建立索引。索引訊息長這樣:
0:000> !index
Indexed 1/1 keyframes
Successfully created the index in 96ms.💡 keyframe 是什麼? 官方定義:追蹤檔中用來建立索引的位置,自動產生,追蹤檔越大 keyframe 越多。索引的目的是讓記憶體值的查詢更準確、其他偵錯操作更有效率。
基本導航指令——TTD 的設計非常好記:指令後面加一個減號,就是往回走。
| 指令 | 作用 |
|---|---|
p- | Step Back(往回單步,不進入函式) |
t- | Trace Back(往回單步,會進入函式) |
g- | Go Back(往回執行,直到遇到事件或追蹤起點) |
g- 執行到追蹤起點時的輸出長這樣:
0:000> g-
TTD: Start of trace reached.
(3f78.4274): Break instruction exception - code 80000003 (first/second chance not available)
Time Travel Position: 29:0
ntdll!ZwTestAlert+0x14:
00007ffc`61f789d4 c3 ret注意那行 Time Travel Position: 29:0——這是 TTD 的時間座標,格式是 序號:步數。你在追蹤檔裡的每一個位置都有這麼一組座標,它也是跟同事協作時最有價值的東西:把位置字串貼給對方,對方用 !tt 就能跳到完全相同的時間點。
!tt 跳到指定位置,兩種寫法:
0:000> !tt 500:000> !tt 1A0:12F規則是:0 到 100 之間的十進位數字 = 跳到追蹤檔的百分比位置(!tt 50 就是跳到一半);#:# 形式的十六進位數字 = 跳到精確位置。
!positions 列出所有作用中執行緒目前所在的時間位置(輸出中 > 標示目前執行緒、* 標示正在執行中的執行緒):
0:000> !positions
>*Thread ID=0x1C74 - Position: F:2
Thread ID=0x1750 - Position: A5:0
Thread ID=0x3FFC - Position: 200:0
* indicates an actively running thread⚠️ 這裡有個新手一定會踩的坑,官方特別寫了一段註記:~s# 切換執行緒不會改變目前在追蹤檔裡的位置,而 !tt 會。差別在於——用 !tt 時間旅行到另一個執行緒的位置後,你(和偵錯器)從記憶體讀到的所有值,都是該位置的值;用 ~s# 切換時,偵錯器內部的目前位置沒有變,而所有記憶體查詢都以那個內部位置為準。看到記憶體值跟你預期的不一樣,先確認你是用哪一個指令切過去的。
步驟六:用 dx + LINQ 把「找 bug」變成「下查詢」
這是 TTD 和其他除錯手段拉開差距的地方。TTD 會在偵錯器資料模型裡掛上一組物件,偵錯追蹤檔時自動載入,可以用 dx 指令查詢。
先看有哪些東西可以查:
0:000> dx @$curprocess.TTD0:000> dx @$cursession.TTD行程層級提供 Index、Threads、Events、DebugOutput、Lifetime(整份追蹤的生命週期範圍)、SetPosition() 等;工作階段層級則提供 Calls()、Memory()、MemoryForPositionRange()、Data、Analyzers、Bookmarks、Checkers 等。
查詢一:這份追蹤裡有哪些例外?
0:000> dx @$curprocess.TTD.Events.Where(t => t.Type == "Exception").Select(e => e.Exception)輸出會列出每個例外的代碼、型別與 PC 位址,例如 Exception 0xE06D7363 of type CPlusPlus at PC: 0X777F51D0。這一行指令就取代了「一路 g 過去看它什麼時候炸」的土法煉鋼。
查詢二:某個 API 最後一次呼叫發生在什麼時候?
0:000> dx @$cursession.TTD.Calls("user32!MessageBoxW").OrderBy(c => c.TimeStart).Last()回傳結果包含 ThreadId、TimeStart、TimeEnd、Function、ReturnAddress、ReturnValue、Parameters;官方屬性表未收錄 SystemTimeStart / SystemTimeEnd,但在官方範例中,只有函式名成功解析(非 UnknownOrMissingSymbols)的那幾筆輸出才出現這兩個掛鐘時間欄位(此關聯為站長比對官方範例後的觀察)。拿到 TimeStart,!tt 過去就是命案現場。
查詢三:把所有失敗的錯誤碼統計出來(站長最愛的一招)。
0:000> dx -g @$cursession.TTD.Calls("kernelbase!GetLastError").Where( x=> x.ReturnValue != 0).GroupBy(x => x.ReturnValue).Select(x => new { ErrorNumber = x.First().ReturnValue, ErrorCount = x.Count()}).OrderByDescending(p => p.ErrorCount),d-g 是官方文件所載的格線輸出選項;結尾的 ,d 則是 dx 指令本身的格式指定字元,讓數字以十進位顯示(說明見文末 dx 官方頁)。跑完你會拿到一張「哪個錯誤碼出現幾次」的排行榜——這比逐行讀 log 快太多了,而且它統計的是真實執行過的呼叫,不是你事先想到要記錄的那些。
查詢四:某個模組是在哪個時間點被載入的?
0:000> dx @$curprocess.TTD.Events.Where(t => t.Type == "ModuleLoaded").Where(t => t.Module.Name.Contains("ntdll.dll"))同樣的寫法把 ModuleLoaded 換成 ThreadCreated、ThreadTerminated,就能查執行緒何時建立與結束。
💡 看到
FFFFFFFFFFFFFFFE:0不要慌——官方說明這個位址代表追蹤檔的結束,模組卸載事件經常會標在這個位置。

步驟七:驗證結果
三件事確認你的追蹤檔是健康的:
1. 索引狀態。 用 !index -status 檢查與 .RUN 追蹤檔關聯的 .IDX 索引檔狀態。回覆不是「Index file loaded」就代表索引有問題。
2. 函式名稱不是 UnknownOrMissingSymbols。 這個字串代表偵錯器沒有拿到足夠的符號資訊。官方把三種情況分得很清楚:有 private symbols → 拿到函式名稱與正確的參數清單;只有 public symbols → 拿到函式名稱,參數則是預設的四個 unsigned 64 位元整數;完全沒有符號 → 顯示 UnknownOrMissingSymbols。看到它就回頭修符號路徑,不要繼續往下查。
3. .out 檔。 用命令列錄製時會同時產生 .out 檔,裡面對一般使用者有價值的資訊包括:只在 .out 顯示的錯誤訊息、錄製開始與結束的掛鐘時間、錄製持續多久(simulation time)、是 launch 還是 attach 錄製、以及作業系統版本。向微軟回報 TTD 問題時,.run 和 .out 要一起附上。
🔬 底層機制:TTD 到底在系統的哪一層?
理解這一層,你才會知道它為什麼快不起來、為什麼有些東西錄不到。
第一層:注入與錄製。 TTD 的做法是掛進(hook)目標行程。命令列錄製器解壓後可以看到它的組成:TTDInject.exe(注入器)、TTDLoader.dll(載入器)、TTDRecordCPU.dll(錄製核心)、TTDRecord.dll、以及 ProcLaunchMon.sys(-monitor 用的行程啟動監看驅動程式)。這是使用者模式技術——官方明講「TTD currently supports only user mode operation」,所以你不能拿它追核心模式的行程。要看核心層,那是 LiveKd 與核心傾印的守備範圍,見〈LiveKd 教學:不必真的當機,用 WinDbg 分析正在執行中的 Windows 核心〉。
第二層:錄什麼。 TTD 做的是完整的指令層級追蹤,官方對編碼效率的說法是「平均每條指令編碼後不到一個位元組」。聽起來很小,但官方也指出現代 CPU 每秒可執行數十億條指令,所以「即使每指令一個位元組也很昂貴」——乘起來即為每秒 GB 等級的資料量(此量級為站長依官方兩項數字推算,非官方數字),這就是追蹤檔會爆炸性長大、以及「只錄需要的模組」為何重要的原因。
第三層:回放靠模擬器。 這是最反直覺、也最少人知道的一點:回放時 WinDbg 內部跑的是一個模擬器,它執行被偵錯行程的指令,以重現該行程在錄製中每一個位置的狀態。理解這件事,兩個現象立刻說得通:
- 為什麼是唯讀回放:官方說法是「你可以回到過去,但你不能改變歷史」——讀取記憶體的指令可以用,修改或寫入記憶體的指令不能用。因為模擬器重現的是既定的錄製結果,寫入沒有意義。
- 什麼是 derailment(脫軌):當模擬器發現「重現出來的狀態」與「追蹤檔裡記錄的資訊」對不起來,就會拋出脫軌事件,長這樣:
Derailment event MissingDataDerailment(7) on UTID 2, position 2A550B:108 with PC 0x7FFE5EEB4448 Request address: 0x600020, size: 32官方解釋:這代表位於 0x7FFE5EEB4448 的某條指令(在追蹤位置 2A550B:108)嘗試讀取 0x600020 附近的記憶體,而那塊記憶體不存在於錄製內容中。脫軌通常肇因於錄製器(有時是模擬器)在追蹤更早的某條指令上出的錯。 後果是:脫軌的那個執行緒從脫軌點開始會有一段長度不確定的空白。判斷標準很簡單——你要查的事件如果不在那段空白裡,這份追蹤檔還能用;如果剛好落在空白裡,只能重錄。
第四層:哪些東西進不去。 受保護的系統行程(如 PPL,Protected Process Light)無法被 TTD 注入,因此錄不了。UWP 應用程式不能用「啟動並錄製」,只能附著。至於「在其他工作階段、其他安全性內容、其他認證下執行」的特殊行程,官方的說法是 TTD 目前只錄「可以正常從命令主控台啟動、或在檔案總管裡點擊執行檔或捷徑啟動」的一般行程。
⚠️ 錄不起來或回放怪怪的:官方錯誤對照
A. 提權相關
- 訊息:
WinDbg must be run elevated to support Time Travel Debugging - 處置:以系統管理員身分執行 WinDbg;若已提權仍出現,用有管理員權限的帳戶重裝 WinDbg。
B. 完全錄不起來
先確認 ping.exe、cmd.exe 這種簡單行程能不能錄。都不行的話,依官方說法,TTD 這種侵入式技術會與應用程式虛擬化框架、資訊管理產品、資安軟體或防毒產品互相干擾。官方已知的不相容情境還包括 Microsoft Enhanced Mitigation Experience Toolkit 這類會擋記憶體存取的工具,以及 Electron 應用程式框架(可能錄得起來,但也可能造成被錄製行程死結或崩潰)。
⚠️ 站長提醒:官方在總覽頁的「Things to look out for」提到,遇到權限不足類訊息時可以「暫時停用防毒軟體」試試。這是官方建議,但本文不提供關閉防護的操作步驟——真的要走這條路,請在離線環境進行、只停最短的時間,並在錄製結束後立刻確認防護已恢復。能換一台乾淨的測試機錄,永遠優先於在日常機器上關防護。
C. 追蹤檔本身壞了
看到這幾類訊息,官方判定是 .RUN 追蹤檔不可用、必須重錄:
Replay and log are out of sync at fallback data. Packet type is incorrect "Packet Type"
Replay and log are out of sync at opaque data. Log had already reached the end
Replay exit thread event does not match up with logged event
Logged debug write values are out of sync with replayD. 索引檔有問題
沒有索引檔、或索引檔損毀/不完整時,還是可以偵錯,但官方不建議。處置順序:先跑 !index -force 重建;失敗的話,關閉偵錯器 → 刪除與 .RUN 同名同目錄的 .IDX 檔 → 重新開啟 .RUN 檔讓 WinDbg 自動重建 → 用 !index -status 確認。記得確認追蹤檔所在位置有足夠空間,索引檔通常是追蹤檔的兩倍大。
E. 回放很慢
如果你錄製時同時開著 AppVerifier,官方指出因為 AppVerifier 使用記憶體檢查應用程式的方式,回放體驗會明顯變差。處置:錄製時停用 AppVerifier;不能停用的話,關閉 WinDbg 的 callstack 視窗以改善效能。
F. 查詢查不到任何呼叫
官方列出四個原因:①呼叫語法不對——用 x <call> 驗證,如果 x 回傳的模組名是大寫,查詢就要照用大寫;②該 DLL 在追蹤的那個時間點還沒載入,請先時間旅行到載入之後再查;③該呼叫被 inline 了,查詢引擎追蹤不到;④萬用字元太寬,比對到太多函式,請把查詢寫具體一點。
🔙 萬一翻車:回退步驟
TTD 不改系統設定,但它有兩個「回不去」的副作用,先講怎麼收尾。
情境一:錄完之後目標程式行為異常、或想讓 TTD 脫離
做不到「卸離」——這是設計如此,不是故障。 官方原文:TTD 一旦附著到行程就無法自行移除。正確處置是關閉該應用程式、或結束該行程;錄製結束後追蹤檔會自動寫出磁碟,不會因為你關掉程式就遺失。
情境二:對象是系統關鍵行程,關不掉
官方明載:對於系統關鍵行程,需要重新開機作業系統才能讓 TTD 脫離。所以——別拿 -attach 去玩系統關鍵行程,尤其不要在正式環境這樣做。
情境三:用過 -monitor,想把行程監看驅動程式移除
-monitor 會安裝行程啟動監看驅動程式(ProcLaunchMon.sys),訊息會顯示「Successfully installed the Process Launch Monitor driver」。收尾用:
TTD.exe -cleanup情境四:磁碟被追蹤檔塞爆
.run 與 .idx 都在 -out 指定的位置(未指定時預設在使用者的文件資料夾)。刪除 .idx 是安全的——WinDbg 開啟 .run 時會重建。另外官方提到 .run 檔的壓縮率很好,傳檔前先壓縮。
💡 總結:什麼時候該掏出 TTD
站長我把這幾年在傾印分析上的取捨講白:TTD 不是用來取代 !analyze -v 的,它是用來接手「快照看不出來」的那一類問題。
判斷方式很簡單,問自己一句:「我缺的是崩潰當下的狀態,還是崩潰之前的過程?」
- 缺狀態 → 傾印檔就夠了。成本近乎為零,先看〈WinDbg !analyze -v 完整教學:逐欄位讀懂當機分析報告〉,不要一開始就架 TTD。
- 缺過程,而且問題重現一次很貴 → TTD。官方比較表對它的定位是:擅長複雜 bug、不需事先寫程式碼插樁、可離線重複偵錯、對分析友善、「什麼都錄」;代價是錄製時開銷大、可能錄到超過需要的資料、檔案會很大。
- 只是想穩定抓到當機瞬間的傾印檔 → 那是 ProcDump 的守備範圍,見〈ProcDump 教學:抓出應用程式沒回應與當機瞬間的記憶體傾印檔〉。
三個最容易踩的坑:①先設好符號;②別錄整個行程;③錄之前先想清楚追蹤檔裡會有什麼——它抓的是記憶體內容,不是可以隨手上傳到公開議題追蹤系統的東西。
⚠️ 本文為官方文件與工具行為的整理與判讀(證據等級 E3)。文中所有引述的官方數字與訊息字串均引自 Microsoft Learn;另有少數為站長依官方數字推算的估值(「追蹤檔 × 3」、「每秒 GB 等級」),已於文中逐處標示,全文無站長第一手實測數據。
❓ 常見問題
Q:TTD 可以用來抓藍畫面(BSOD)嗎?
不行。TTD 目前只支援使用者模式,無法追蹤核心模式行程,而 BSOD 屬於核心層事件。藍畫面請走 minidump 路線(見文末延伸閱讀)。
Q:錄一次要準備多少磁碟空間?
官方沒給固定數字,只說「錄幾分鐘就可能長到數 GB」,且刻意不設上限以支援長時間情境。實務估法:預留「追蹤檔 × 3」(索引檔約兩倍大,且要放同一位置)。想控制大小就用 -ring 搭配 -maxFile。
Q:可以在正式環境的伺服器上錄嗎?
技術上可以(官方載明 Windows Server 2016/2019/2022/2025 支援 TTD.exe),但請先評估三件事:錄製有 5x–20x 甚至更高的減速;TTD 附著後無法卸離,系統關鍵行程要靠重開機才能脫離;追蹤檔可能含敏感資料。能在測試環境重現就別在正式環境錄。
Q:同事傳給我 .run 檔,我需要他的 .idx 嗎?
不需要,而且官方建議只分享 .run——索引檔可能和追蹤檔一樣大,而且 WinDbg 載入追蹤檔時會自動建立。真正該一起傳的是出問題的時間位置字串(例如 2A550B:108),對方用 !tt x:y 就能跳到完全相同的執行時間點。
Q:為什麼我查 TTD.Calls("mymodule!MyFunc") 什麼都查不到?
依官方列出的四個原因逐一排除:①語法不對——用 x mymodule!MyFunc 驗證,x 回傳大寫模組名就照著用大寫;②該 DLL 在目前位置還沒載入,先跳到載入之後再查;③函式被 inline,查詢引擎追蹤不到;④萬用字元太寬泛,把查詢寫具體一點。
🔗 延伸閱讀
- WinDbg 記憶體與控制代碼診斷:用 !poolused、!handle、!vm 揪出洩漏元兇——洩漏型問題的另一條路線,不必錄整段執行
- WinDbg 進階指令教學:用 !process、!irp、!thread 追出卡死的驅動程式與 I/O 請求——卡死不是崩潰,先看這篇的等待鏈判讀
- WinDbg 藍畫面 minidump 分析教學 2026|三行輸出找出真兇——核心層當機的標準流程
- Sysmon 教學:替 Windows 建立完整的處理程序與網路連線紀錄——錄不了執行過程時,退而求其次的長期行為紀錄
📎 參考資料來源
📖 第一級|廠商官方:
- Microsoft Learn:Time Travel Debugging – Overview — 2026-08-29 查證
- Microsoft Learn:Time Travel Debugging – Record a trace — 2026-08-29 查證
- Microsoft Learn:Time Travel Debugging – Replay a trace — 2026-08-29 查證
- Microsoft Learn:Time Travel Debugging – TTD.exe command line utility — 2026-08-29 查證
- Microsoft Learn:Introduction to Time Travel Debugging objects — 2026-08-29 查證
- Microsoft Learn:Time Travel Debugging – Troubleshooting — 2026-08-29 查證
- Microsoft Learn:Time Travel Debugging – !tt (time travel) — 2026-08-29 查證
- Microsoft Learn:dx (Display Debugger Object Model Expression) — 2026-08-29 查證
- Microsoft Learn:Install WinDbg — 2026-08-29 查證
⚠️ 本文核心事實以第一級為準;全文未使用第二級來源。
📅 本文查證戳記:2026-08-29 依據 Microsoft Learn 官方文件撰寫(證據等級 E3,非第一手實測)。
若你在後續版本遇到步驟失效,歡迎在留言區回報,站長會更新文章。
