מבוא לאיסוף crash dump ב-Windows - WER,‏ ProcDump,‏ WinDbg

· עודכן בתאריך: · · פיתוח Windows, חקירת תקלות, crash dump, WER, ProcDump, WinDbg

כשמתחילים לראות אפליקציית Windows ש”נופלת מדי פעם”, יש הרבה מצבים שאי אפשר לעקוב אחריהם רק עם לוגים.

בפרט קשים המקרים הבאים:

  • קורה רק בסביבת הלקוח
  • הודעת החריגה נתפסה, אבל חסר הקשר הקריאה
  • מעורבים לא רק ה-managed בצד C# / .NET, אלא גם COM,‏ P/Invoke, DLL נייטיבי, SDK של ספק חיצוני
  • קורס רק אחרי הרצה ארוכה

במקרים כאלה, ה-crash dump יעיל. אם שומרים לקובץ את מצב התהליך ברגע הקריסה, אפשר לקרוא בדיעבד את קוד החריגה, את מחסנית ה-thread שקרס, את המודולים שהיו טעונים, ואת חלק מהזיכרון או כולו.

ב-Windows, קל יותר לחשוב בסדר הזה: קודם LocalDumps של WER, ואם צריך - ProcDump של Sysinternals, ואם רוצים שליטה נוספת - MiniDumpWriteDump. המאמר הזה מסדר את הצעד הראשון באיסוף crash dump, על בסיס אפליקציות שולחן עבודה ל-Windows, אפליקציות שרצות ברקע, שירותי Windows וכלי חיבור לציוד.

הסדר לחשיבה על אמצעי איסוףתרשים שמראה שבאיסוף crash dump ב-Windows, קל יותר לחשוב בסדר הזה - קודם LocalDumps של WER, ואם צריך ProcDump של Sysinternals, ואם רוצים שליטה נוספת MiniDumpWriteDump.קודם WER LocalDumpsאם צריך, ProcDumpואם רוצים שליטה נוספת, MiniDumpWriteDump

איור 1: מתחילים מהפיצ’ר המובנה ומוסיפים כלים רק ככל שחסר.

מונחים שחוזרים לאורך המאמר הזה

לפני שממשיכים, נקבע אותם בקצרה. אם הם נשארים מעורפלים, הפרקים הבאים יהיו לא ברורים.

מונח משמעות
‏PDB קובץ מידע ניפוי באגים שנוצר בזמן הבנייה. טבלת המרה שממירה כתובת לשם פונקציה או מספר שורה
סמלים (symbols) מידע התאמה בין כתובת לשם. מסופק מ-PDB או משרת סמלים. בלעדיו, מחסנית הקריאות היא רשימת כתובות בלבד
‏first chance exception השלב מיד אחרי שחריגה מתרחשת, לפני שה-handler של האפליקציה עיבד אותה. אם האפליקציה תופסת אותה ב-catch, העיבוד ממשיך
‏second chance exception השלב שבו האפליקציה לא הצליחה לטפל בחריגה, והתהליך בדרך לסיום כחריגה לא מטופלת. בדרך כלל זה מה שמכונה “נפל”
‏postmortem debugger debugger שה-OS מפעיל אוטומטית בזמן קריסה. נרשם כהתנהגות של המחשב כולו בזמן קריסה
‏minidump /‏ full dump ההבדל בכמות הזיכרון שנכלל ב-dump. מפורט בפרק 7

1. קודם כל - המסקנה

הנה קודם כל הנקודות החשובות ביותר.

  • ראשית, בטוח יותר להגדיר את WER LocalDumps לפי אפליקציה. בלי כלי נוסף, אפשר להשאיר dump מקומי אחרי קריסה.
  • בחקירה בשטח עם שיעור שחזור נמוך, או כשרוצים לראות גם first chance exception / hang, משתמשים ב-ProcDump.
  • איסוף עצמאי כדאי לשקול אחרון. מספיק לשקול MiniDumpWriteDump רק כשמתעורר צורך אמיתי.
  • חשוב לא פחות מה-dump עצמו הוא שמירת ה-PDB והקבצים הבינאריים המופצים. גם אם יש dump, בלי סמלים כמות המידע הקריא קטנה משמעותית.
  • ‏full dump חזק, אבל גם הגודל וסיכון דליפת מידע רגיש חזקים. חשוב לקבוע מראש מיקום אחסון, מספר שמורים, הרשאות גישה, ונוהל שיתוף.

ההרכב המומלץ לשלב ההתחלה מתמצה בערך כך.

סביבה ההרכב הראשוני
מחשב פיתוח / בדיקה הגדרת WER LocalDumps לפי אפליקציה, בהתחלה DumpType=2 שהוא full dump
סביבת לקוח / מחשב בשטח בחירה בין DumpType=1 ל-2 לפי היקף וצורכי סודיות. הוספת ProcDump רק במקרה הצורך
הרצה ארוכה או חקירת hang בנוסף ל-WER, לשקול -h או -e 1 של ProcDump
רוצים לכלול UI ייחודי או לוגים מצורפים איסוף עצמאי עם MiniDumpWriteDump, בהנחה של תהליך נפרד

בקיצור: קודם WER, אחר כך ProcDump, ולבסוף איסוף עצמאי. אם מתחילים בסדר הפוך, בדרך כלל התכנון מכביד.

מפת הידע של המאמר

באיסוף crash dump באפליקציית Windows, קודם מכניסים את WER LocalDumps שניתן להגדיר לפי אפליקציה בלי כלי נוסף, מוסיפים ProcDump כשרוצים לראות גם hang או first chance exception או לנטר תהליך שכבר רץ, ורק כשעולה צורך בפונקציית אבחון עצמאית שוקלים איסוף עצמאי עם MiniDumpWriteDump - זה הסדר הבטוח. סוג ה-dump כרוך בפשרה בין עומק המידע לגודל בין minidump ל-full dump, ותהליך CLR של .NET נאסף כ-full גם בציון MiniPlus של ProcDump. בלי בדיקת הרשאת הכתיבה לתיקיית היעד, האיסוף עצמו נכשל בשקט, וה-dump שהתקבל הופך למידע קריא רק בשילוב עם PDB וניתוח ב-WinDbg.

מפת הידע של איסוף crash dump ב-Windows (WER / ProcDump / WinDbg)תרשים שמראה ש-WER LocalDumps,‏ ProcDump ו-MiniDumpWriteDump הם אמצעי איסוף crash dump שכדאי לשקול בסדר הזה, ושבחירת סוג ה-dump, בדיקת ה-ACL של יעד השמירה, וניתוח עם WinDbg יחד עם PDB הם רצף אחד.צריך לקדום לצריך לקדום למממש אתמממש אתמשתמש במשתמש במשתמש במשתמש במענה מומלץ לשימוש לא מומלץ למחייבמשתמש במשתמש במשתמש בשימוש לא מומלץ למממש אתצריך לקדום למחייבנבדק באמצעותמענה מומלץ לשימוש לא מומלץ לWER LocalDumpsProcDumpWinDbgMiniDumpWriteDump‏crash dump (תמונת קריסה)‏minidump‏full dump‏MiniPlus dumpחקירת הסיבה בגבול הנייטיב‏ACL של תיקיית שמירת ה-dumpfirst chance exceptionsecond chance exceptionזיהוי תקיעהPostmortem debugger‏PDB (מסד נתוני התוכנית)מנגנון עצמי לשמירת מידע אבחוניNotMyFault

בתרשים, קו מלא מציין קשר שמתקיים תמיד וקו מקווקו מציין קשר מותנה (תנאי ההתקיימות מפורטים בהסבר של כל קשר בעמוד המפורט). רשימת כל הקשרים (סך הכול 21, עם אסמכתה ורמת ודאות) והגדרות המושגים המרכזיים מרוכזות בעמוד המפורט של מפת הידע (ביפנית). נתונים: JSON-LD / Turtle

2. מה אפשר ללמוד מ-crash dump

‏‏crash dump הוא “תצלום סטילס של הרגע ההוא”. יותר קרוב לתצלום זירת תאונה מאשר למצלמת אבטחה.

לכן, המידע הבא בדרך כלל קל למדי להשגה.

  • באיזה קוד חריגה קרס
  • איזה thread קרס
  • מחסנית הקריאות באותו רגע
  • אילו מודולים היו טעונים
  • בהתאם לכמות הזיכרון שנכלל, מצב ה-heap ותוכן האובייקטים

מצד שני, יש דברים שה-dump לבדו נוטה שלא לספק.

  • ציר הזמן שהוביל לשם
  • מגמת עלייה מכמה שעות קודם
  • מצב חיצוני של תקשורת או ציוד
  • הקלט או ההקשר העסקי שקדם לכך

לכן, בפועל, הבסיס הוא לא לנסות להסתפק ב-dump לבדו, אלא לשלב אותו עם לוגים ו-heartbeat.

שילוב dump ולוגיםתרשים שמראה ש-crash dump חזק במיוחד במצב הרגע עצמו, כמו תצלום זירת תאונה, ולוגים ו-heartbeat משלימים את ציר הזמן והמצב החיצוני, ולכן הבסיס הוא לשלב את שניהם בחקירה.crash dump (תצלום סטילס)חוקרים בשילובלוגים ו-heartbeat (ציר זמן)חזק בקוד חריגה ובמחסניתחזק בהתקדמות עד לרגע ההוא

איור 2: ה-dump שהוא תצלום סטילס והלוג שהוא ציר זמן חזקים בתחומים שונים לגמרי.

3. מבט כללי על שיטות האיסוף

ב-Windows, ארבע השיטות שכדאי להכיר בשלב ההתחלה לאיסוף dump הן אלה.

שיטה מתאימה למקרה חוזקה נקודה לתשומת לב
‏WER LocalDumps איסוף קריסות שרוצים ראשית להשאיר קבוע תקן של Windows. נוח להגדרה לפי אפליקציה בעיקר מתאים לקריסות. חלש ב-hang ובתנאים עדינים
‏ProcDump חקירה עם שיעור שחזור נמוך, hang,‏ first chance exception טריגרים רבים. נוח להפעיל בשטח דורש הפעלת כלי חיצוני
יצירת dump מ-Task Manager רוצים לתפוס ידנית את המצב הנוכחי ניתן לתפוס באופן מיידי דרך GUI לא איסוף אוטומטי
MiniDumpWriteDump רוצים לבנות פונקציית אבחון עצמאית קל לשלב לוגים מצורפים ומטא-דאטה ייחודית מימוש רשלני עלול לגרום לתקלה נוספת

מה שהכי חשוב למתחילים הוא לקבוע קודם באילו תנאים, לאן, ובאיזה גודל אוספים - לפני שבוחרים “עם מה” אוספים.

מה שקובעים לפני בחירת הכליתרשים שמראה שבאיסוף crash dump חשוב לקבוע קודם באילו תנאים, לאן, ובאיזה גודל אוספים, ורק אחר כך לעבור לבחירת הכלי.באילו תנאים אוספים3 דברים שקובעים קודםלאן מוציאיםבאיזה גודלורק אז בוחרים כלי

איור 3: אחרי שקובעים תנאים, יעד וגודל, בחירת הכלי כבר לא מבלבלת.

4. ההמלצה הראשונה - WER LocalDumps

4.1 ערכי הרישום הראשונים לבדיקה

ל-‏Windows Error Reporting (‏WER) יש פיצ’ר בשם LocalDumps, ששומר dump ברמת user mode לוקלית אחרי קריסה. מכיוון שלא צריך להפיץ כלי נוסף, זה נוח למדי כצעד ראשון.

המפתח הבסיסי הוא כאן.

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps

אפשר להניח כאן הגדרה גלובלית, אבל בפועל נוח יותר לרכז אותה במפתח משנה לפי אפליקציה.

היכן ממקמים את הגדרת LocalDumpsתרשים שמראה שמתחת למפתח LocalDumps אפשר להניח הגדרה גלובלית, אבל בפועל נוח יותר לרכז אותה במפתח משנה לפי אפליקציה כמו MyApp.exe.מפתח LocalDumpsהגדרה גלובלית ישירות תחתיומפתח משנה לפי אפליקציהנוח יותר בפועל

איור 4: אותו מפתח, אבל ריכוז לפי מפתח משנה של שם האפליקציה מצמצם את היקף ההשפעה.

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MyApp.exe

שלושת הערכים הראשונים לבדיקה הם:

ערך משמעות המלצה ראשונית
DumpFolder יעד פלט ה-dump להקצות תיקייה ייעודית
DumpCount מספר שמורים להתחיל מ-5 עד 10
DumpType 0=מותאם אישית, 1=מיני, 2=מלא בהתחלה 2, ואם הגודל בעייתי - 1

4.2 דוגמה להגדרה לפי אפליקציה

לדוגמה, עבור MyApp.exe, אם רוצים להשאיר עד 10 dump מלאים תחת C:\CrashDumps\MyApp, אפשר להגדיר כך בהתחלה.

reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MyApp.exe" /f
reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MyApp.exe" /v DumpFolder /t REG_EXPAND_SZ /d "C:\CrashDumps\MyApp" /f
reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MyApp.exe" /v DumpCount /t REG_DWORD /d 10 /f
reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MyApp.exe" /v DumpType /t REG_DWORD /d 2 /f

הדוגמה הזו כוללת ארבע נקודות חשובות.

  • מוגבל ל-MyApp.exe ולא גלובלי
  • יעד הפלט מופרד לתיקייה ייעודית
  • בהתחלה full dump
  • מספר השמורים מוגבל ל-10

4.3 בדיקה שההגדרה עובדת

אחרי שמכניסים את ההגדרה, בטוח יותר לוודא לפחות פעם אחת בסביבת בדיקה לפני שממתינים להתרחשות טבעית בייצור.

4 הדברים שכדאי לבדוק:

  1. האם .dmp נוצר בתיקייה המצופה
  2. האם הגודל תואם את התכנון התפעולי
  3. האם ניתן לפתוח ב-WinDbg
  4. האם ה-crash נראה בלוג ה-Application ב-Event Viewer
זרימת האימות אחרי ההגדרהתרשים שמראה שאחרי הכנסת ההגדרה, לפני ההמתנה להתרחשות טבעית בייצור, בודקים פעם אחת בסביבת בדיקה - מפילים בכוונה, בודקים אם ה-dump וגודלו כמצופה, בודקים פתיחה ב-WinDbg, ובודקים את הלוג ב-Event Viewer.מכניסים את ההגדרהמפילים בכוונה בסביבת בדיקהבודקים אם ה-dump נוצר ומה גודלובודקים אם ניתן לפתוח ב-WinDbgבודקים את הלוג ב-Event Viewer

איור 5: לפני ההמתנה להתרחשות טבעית בייצור, מוודאים פעם אחת בסביבת בדיקה.

4.4 קוד מינימלי להפלה מכוונת

גם אם אומרים “לוודא”, אי אפשר לחכות לקריסה אמיתית - זה לא בדיקה ממשית. נוח להכין מראש EXE קטן שמפיל את עצמו בכוונה לצורך הבדיקה.

ב-.NET, מספיקה אפליקציית console שרק זורקת חריגה לא מטופלת. חריגה לא מטופלת מ-managed ב-.NET מסיימת את התהליך, ולכן היא הופכת אוטומטית ליעד עבור WER.

// CrashTest.csproj: <TargetFramework>net8.0</TargetFramework>
using System;
using System.Threading;

internal static class Program
{
    private static void Main()
    {
        Console.WriteLine($"PID={Environment.ProcessId} / 3 秒後に落とします。");
        Thread.Sleep(3000);

        throw new InvalidOperationException("intentional crash for dump collection test");
    }
}

אם רוצים לבדוק את הצד הנייטיבי, קרוב יותר לגרום ל-access violation (‏0xC0000005). מוסיפים volatile כדי שהאופטימיזציה לא תמחק את הפעולה.

// crash_test.cpp / C++17 / MSVC
int main()
{
    volatile int* p = nullptr;
    *p = 1;  // כאן מתרחש STATUS_ACCESS_VIOLATION
    return 0;
}

יש נקודה אחת שקל לפספס כאן. שם מפתח המשנה של LocalDumps חייב להיות זהה לשם קובץ ה-EXE שמפילים כעת. אם יוצרים רק את המפתח של MyApp.exe ומפילים את CrashTest.exe, ברור שלא ייווצר dump. בזמן הבדיקה, או יוצרים מפתח זמני עבור CrashTest.exe, או בודקים דרך ההגדרה הגלובלית.

המלכודת של התאמת שם מפתח המשנהתרשים שמראה ששם מפתח המשנה של LocalDumps חייב להתאים לשם קובץ ה-EXE שמפילים בפועל, ולכן אם יוצרים רק את המפתח של MyApp.exe ומפילים CrashTest.exe, לא ייווצר dump, ובזמן הבדיקה יוצרים מפתח זמני או בודקים דרך ההגדרה הגלובלית.יוצרים רק את המפתח של MyApp.exeמפילים את CrashTest.exeלא נוצר dumpמתאימים את שם המפתח לשם ה-EXE שמפילים

איור 6: פער בין שם מפתח המשנה לשם ה-EXE הוא מלכודת נפוצה שגורמת לבדיקה להיכשל בשקט.

גם NotMyFault של Sysinternals עולה לעיתים קרובות ככלי “להפיל בכוונה”, אבל הוא מיועד להפיל או לגרום ל-hang למערכת Windows עצמה כדי ליצור dump של מסך כחול, ודורש הרשאת מנהל. עבור אימות LocalDumps של אפליקציית user mode, EXE קטן עצמאי כמו למעלה בטוח וודאי יותר.

5. מקרים שבהם משתמשים ב-ProcDump

לעיתים קרובות WER מספיק, אבל יש גם מקרים שבהם ProcDump שימושי.

  • רוצים להימנע ממצב קבוע ברישום
  • רוצים לנטר רק תהליך שכבר רץ
  • רוצים לנטר רק מההפעלה הבאה ואילך
  • רוצים לראות first chance exception
  • רוצים לתפוס hang
  • רוצים לאסוף לפי מונה ביצועים או תנאי מסוים

5.1 האפשרויות הנפוצות

אם מצמצמים לאלה שנפוצות בשלב ההתחלה, מספיק לזכור את אלה כדי להתמודד עם רוב המצבים ב-ProcDump.

אפשרות משמעות
-ma ‏full dump
-mp ‏MiniPlus dump
-mc <Mask> ‏dump מותאם אישית. מציינים bitmask הקסדצימלי של MINIDUMP_TYPE
-e ‏dump בחריגה לא מטופלת
-e 1 ‏dump בחריגת first chance / second chance
-h ‏dump בחלון שנתקע
-w המתנה להפעלת התהליך היעד
-x הפעלת התהליך היעד וניטורו
-n מספר ה-dump המרבי
-accepteula אישור אוטומטי של אישור ה-EULA הראשוני

5.2 דוגמאות פקודה נפוצות

תהליך שכבר רץ, full dump בחריגה לא מטופלת

procdump -accepteula -ma -e 1234 C:\CrashDumps\MyApp

המתנה להפעלה הבאה, full dump בחריגה לא מטופלת

procdump -accepteula -ma -e -w MyApp.exe C:\CrashDumps\MyApp

מפעילים בעצמנו וממשיכים לנטר

procdump -accepteula -ma -e -x C:\CrashDumps\MyApp MyApp.exe

רוצים לתפוס גם first chance exception

procdump -accepteula -ma -n 3 -e 1 MyApp.exe C:\CrashDumps\MyApp

רוצים לתפוס hang

procdump -accepteula -h MyApp.exe C:\CrashDumps\MyApp

5.3 למה -i הוא לא הצעד הראשון

ל-ProcDump יש גם שימוש שבו רושמים אותו כ-postmortem debugger עם -i. זה חזק, אבל חודר להתנהגות המחשב כולו בזמן קריסה, ולכן זה כבד מדי כצעד ראשון בשלב ההתחלה.

לכן, נוח יותר להתחיל מ-הגדרת WER לפי אפליקציה, או מ--w /‏ -x /‏ ציון PID של ProcDump.

למה -i לא הצעד הראשוןתרשים שמראה שה-i-‏ של ProcDump הוא שימוש חזק שרושם postmortem debugger, אבל הוא חודר להתנהגות המחשב כולו בזמן קריסה, ולכן בשלב ההתחלה נוח יותר להתחיל מהגדרת WER לפי אפליקציה או מ-w,‏ x, וציון PID של ProcDump.רישום עם -i של ProcDumpחודר להתנהגות המחשב כולוכבד מדי לצעד הראשון בשלב ההתחלהמתחילים בהיקף של אפליקציה בודדתהגדרת WER לפי אפליקציה‏-w,‏ -x, או ציון PID של ProcDump

איור 7: מתחילים מכניסה שהיקף השפעתה מוגבל לאפליקציה בודדת.

6. איך חושבים על שימוש ב-MiniDumpWriteDump לאיסוף עצמאי

איסוף עצמאי מתאים למקרים כמו אלה.

  • רוצים כפתור “שמור מידע אבחוני” מה-UI
  • רוצים לצרף יחד עם ה-dump גם לוגים, הגדרות ו-trace ID
  • רוצים לרכז גם תהליכי בן או תהליכי עזר קשורים
  • רוצים להוסיף מיסוך או דחיסה ייחודיים לפני העלאה

ה-API המרכזי כאן הוא MiniDumpWriteDump.

עם זאת, יש כאן קצת אופי מיוחד. שתי הנקודות שהכי חשוב לא לפספס בהתחלה הן:

  1. אם אפשר, לקרוא מתהליך נפרד מזה שנוצר ממנו ה-dump
  2. להתייחס למשפחת ה-API של DbgHelp כמניחה single-thread
שתי הנקודות שלא כדאי לפספס באיסוף עצמאיתרשים שמראה שבאיסוף עצמאי עם MiniDumpWriteDump, שתי הנקודות שחשוב לא לפספס הן לקרוא אם אפשר מתהליך נפרד, ולהתייחס למשפחת DbgHelp כמניחה single-thread.איסוף עצמאי עם MiniDumpWriteDumpקוראים מתהליך נפרדDbgHelp מניח single-threadמימוש רשלני גורם לתקלה

איור 8: האופי המיוחד של איסוף עצמאי מתרכז בשתי נקודות - מאיפה קוראים ואיזה thread.

7. איך בוחרים בין minidump,‏ full dump וגודל ביניים

זו נקודה שהרבה אנשים מתלבטים בה. הנה טבלה לבחירה מעשית.

סוג מתאים למקרה יתרון נקודה לתשומת לב
‏minidump רוצים להטמיע קודם באופן רחב, רוצים לשתף בקלות קטן, קל להעברה חלש בשחזור עומק המצב
‏full dump רוצים לתת עדיפות לחקירת הסיבה, חשד בגבול נייטיב או ב-heap הרבה מידע נגיש גדול, סיכון דליפת מידע רגיש גבוה
‏MiniPlus /‏ Custom mini לא מספיק, full כבד מדי איזון בין השניים דורש ידע לכוונון

ההמלצה למתחילים די פשוטה.

  • במחשב פיתוח / בדיקה - full dump
  • בסביבת הלקוח - בוחרים בין mini ל-full לפי תנאי התפעול
  • כשיש חשד להשחתת זיכרון, DLL נייטיבי, COM,‏ P/Invoke, או תקלת מצב אחרי הרצה ארוכה, עדיף לנטות לכיוון full
הבחירה הראשונית בסוג ה-dumpתרשים שמראה שבמחשב פיתוח או בדיקה בוחרים full dump, בסביבת הלקוח בוחרים בין mini ל-full לפי תנאי התפעול, וכשיש חשד להשחתת זיכרון, גבול נייטיב או תקלת מצב אחרי הרצה ארוכה - נוטים לכיוון full.מחשב פיתוח / בדיקהסביבת לקוחחשד להשחתה או גבול נייטיבבאיזו סביבה אוספיםfull dumpmini או full לפי תנאי תפעול

איור 9: כשמתלבטים, קובעים לפי הסביבה, וככל שהחשד חזק יותר - נוטים ל-full.

7.1 איך בפועל מציינים MiniPlus /‏ Custom

רק לגבי השורה השלישית בטבלה, אופן הציון קצת פחות ברור, ולכן נוסיף הבהרה.

במקרה של WER LocalDumps, קובעים את DumpType ל-0 (מותאם אישית), ומכניסים ל-CustomDumpFlags שילוב סיביות של MINIDUMP_TYPE. ‏CustomDumpFlags נבדק רק כש-DumpType=0, וברירת המחדל היא 0x00000121 (שילוב של MiniDumpWithDataSegs,‏ MiniDumpWithUnloadedModules ו-MiniDumpWithProcessThreadData).

reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MyApp.exe" /v DumpType /t REG_DWORD /d 0 /f
reg add "HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps\MyApp.exe" /v CustomDumpFlags /t REG_DWORD /d 0x121 /f

במקרה של ProcDump, ‏-mp הוא MiniPlus, ו--mc <Mask> הוא מותאם אישית.

procdump -accepteula -mp -e MyApp.exe C:\CrashDumps\MyApp

‏MiniPlus, למרות שמו, בתוכן שלו קרוב למדי ל-full. לפי התיעוד, הוא כולל את כל הזיכרון הפרטי (private), וגם את כל ה-image / mapped memory שהוא read/write, ומעליהם מוציא רק את שטח הזיכרון הפרטי המקסימלי אם הוא עולה על 512MB, כדי לצמצם את הגודל. התוצאה היא מצב שבו “מפורט כמו full dump, אבל בגודל של 10%-75% ממנו”.

עם זאת, יש שתי הערות.

  • בתהליכי CLR, בגלל מגבלות בניפוי באגים, גם ציון -mp יגרום לאיסוף כ-full (‏-ma). לצפות לצמצום גודל דרך MiniPlus באפליקציית .NET לרוב לא יתממש
  • אם המניע לצמצום הגודל הוא “רוצים להפחית דליפת מידע רגיש”, עדיף לחשוב לכיוון minidump ולא לכיוון MiniPlus - זה ישיר יותר
המיקום והמגבלה של MiniPlusתרשים שמראה ש-MiniPlus כולל כמעט את כל הזיכרון הפרטי, מוציא רק אזורי זיכרון פרטי ענקיים, ולכן קטן ומפורט יותר מ-full, אבל בתהליכי CLR הוא נאסף כ-full בכל זאת.במקרה של תהליך CLRאיסוף עם MiniPlusכולל כמעט את כל הזיכרון הפרטימוציא רק אזורי זיכרון פרטי ענקייםקטן יותר ומפורט יותר מ-fullנאסף בפועל כ-full

איור 10: תוכן MiniPlus קרוב ל-full, ובאפליקציית .NET לא מקבלים את צמצום הגודל.

8. דברים שכדאי לקבוע מראש בתפעול

איסוף dump נוטה להיכשל בגלל תפעול הרבה יותר מאשר בגלל המימוש. הנה הדברים שכדאי לקבוע מראש.

8.1 איך שומרים PDB וקבצים בינאריים

זו הנקודה הכי חשובה.

  • הגרסה המדויקת של ה-EXE / DLL שהופצו
  • ה-PDB התואם לגרסה הזו
  • ה-commit ה-pipeline של הבנייה שממנו נוצר
  • מידע גרסה של המתקין וקבצי ההפצה

8.2 לאן מוציאים וכמה שומרים

‏full dump יכול להיות גדול למדי. בטוח יותר לקבוע מראש את יעד הפלט ואת מדיניות השמירה.

  • לא להשאיר אחסון ישירות תחת כונן המערכת
  • להפריד לתיקייה ייעודית
  • להגביל עם DumpCount או -n
  • להפריד בין אחסון ראשוני לאחסון ארוך טווח

8.3 מי רשאי לצפות

ל-full dump יש סיכוי שיתערבב בו מידע רגיש או מידע אישי.

  • הגדרות ב-plaintext
  • connection string
  • token או פרטי הזדהות
  • מידע עסקי שטופל ממש לפני כן
  • נתיבי קבצים או שמות משתמשים

לכן, יש צורך לקבוע גם “מי רשאי לגעת” יחד עם תכנון “האיסוף” עצמו.

3 דברים שקובעים מראש בתפעולתרשים שמראה שבאיסוף crash dump, שנוטה להיכשל בגלל תפעול יותר מאשר בגלל מימוש, קובעים מראש את שמירת ה-PDB והקבצים הבינאריים, את יעד הפלט ומספר השמורים, ואת מדיניות הגישה של מי רשאי לצפות.שמירת PDB וקבצים בינארייםקובעים מראשיעד פלט ומספר שמוריםמי רשאי לצפותנוטה להיכשל יותר בתפעול מאשר במימוש

איור 11: כישלון באיסוף dump נובע לרוב מהיעדר החלטות תפעוליות מראש.

9. מסלול הניתוח המהיר ביותר אחרי שהתקבל dump

אחרי שמקבלים dump, מה שעושים ראשית פשוט למדי.

9.1 מתקינים את WinDbg

היום קל להתקין את WinDbg דרך Microsoft Store או winget.

winget install Microsoft.WinDbg

9.2 פותחים את ה-dump

windbg -z C:\CrashDumps\MyApp\MyApp_YYMMDD_HHMMSS.dmp

שם הקובץ כאן הוא השם שברירת המחדל של ProcDump נותנת. שם ברירת המחדל של ProcDump הוא PROCESSNAME_YYMMDD_HHMMSS.dmp, ואפשר להשתמש כמציין החלפה ב-PROCESSNAME,‏ PID,‏ EXCEPTIONCODE,‏ YYMMDD,‏ HHMMSS.

מצד שני, ‏WER LocalDumps יוצר קבצים עם שם שונה מ-ProcDump. כללי השם לא מפורטים ב-Microsoft Learn, ולכן במקום לנחש את השם, ודאי יותר להסתכל על תיקיית הפלט ממוינת לפי תאריך עדכון.

dir /o-d "C:\CrashDumps\MyApp\*.dmp"

אם לא הגדרתם DumpFolder, יעד ברירת המחדל הוא %LOCALAPPDATA%\CrashDumps. עם זאת, קריסה של שירות יוצאת לתיקיית הפרופיל של חשבון ההרצה. עבור שירות System, זה %WINDIR%\System32\Config\SystemProfile, ועבור Network Service /‏ Local Service, זה תחת %WINDIR%\ServiceProfiles. אם נדמה ש”ה-dump לא נוצר”, זה המקום הראשון לחשוד בו.

איפה מחפשים כשה-dump לא נמצאתרשים שמראה שכשלא הגדירו DumpFolder, ברירת המחדל היא CrashDumps תחת LOCALAPPDATA, וקריסה של שירות יוצאת לתיקיית הפרופיל של חשבון ההרצה, ולכן כשה-dump לא נמצא, שם הוא המקום הראשון לחשוד בו.אפליקציה רגילהשירותה-dump לא נמצאבאיזו צורה זה רץCrashDumps תחת LOCALAPPDATAתיקיית הפרופיל של חשבון ההרצהSystemProfile או ServiceProfiles

איור 12: יעד ברירת המחדל שונה לפי החשבון, ולכן חושדים קודם בהיכן מחפשים.

9.3 מגדירים סמלים

קודם מפעילים גישה לסמלים הציבוריים של Microsoft, ואז מוסיפים את מיקום ה-PDB שלכם.

.symfix C:\Symbols\Microsoft
.sympath+ C:\Symbols\MyApp
.reload

9.4 קודם רואים את הניתוח האוטומטי

!analyze -v

ואז, בודקים לפי הסדר:

  • מה קוד החריגה
  • מהו ה-faulting module
  • עד כמה הקוד שלכם נראה במחסנית
  • האם יש המתנה או חסימה חשודה בשרשורים אחרים חוץ מה-thread של החריגה
מסלול הניתוח המהיר ביותר אחרי שהתקבל dumpתרשים שמראה שמתקינים WinDbg, פותחים את ה-dump, מגדירים סמלים ציבוריים ואת ה-PDB שלכם, ואז רואים ראשית את הניתוח האוטומטי של analyze -v, ואחר כך בודקים בסדר את קוד החריגה, את ה-faulting module, את הופעת הקוד שלכם ואת החסימות ב-threads אחרים.מתקינים WinDbgפותחים את ה-dumpמגדירים סמלים ו-PDBקודם רואים ניתוח אוטומטיקוראים בסדר את קוד החריגה ואת המחסנית

איור 13: פתיחה, מעבר דרך הסמלים, והתחלה בקריאת הניתוח האוטומטי - זהו המסלול המהיר ביותר.

10. מוקשים נפוצים

10.1 ה-dump התקבל, אבל אין PDB

זה קורה למדי הרבה. גם אם איסוף ה-dump הצליח, חומר הקריאה חסר. עדיף להכניס את תכנון שמירת ה-PDB באותו זמן שמכניסים את הגדרת האיסוף.

10.2 לא בודקים את ה-ACL של DumpFolder

בשירותים ותהליכים עם הפרדת הרשאות, קל שכאן ייכשל בשקט. קודם מוודאים אם “התהליך הזה באמת יכול לכתוב”. גם Microsoft Learn כותב שאם משתמשים בנתיב שאינו ברירת המחדל, יש לוודא ש”ל-ACL יש הרשאה שהתהליך שקרס יכול לכתוב אליה”.

את ה-ACL הנוכחי אפשר לראות עם icacls.

icacls C:\CrashDumps\MyApp

אם חסרה הרשאת כתיבה, מוסיפים M (שינוי) לחשבון ההרצה. תיקיית ה-dump זקוקה לאותה הרשאה גם עבור הקבצים תחתיה, ולכן מוסיפים (OI) ו-(CI) כדי שההרשאה תעבור בירושה.

rem לדוגמה: שירות שרץ תחת Network Service
icacls C:\CrashDumps\MyApp /grant "NT AUTHORITY\NETWORK SERVICE:(OI)(CI)M"

(OI) הוא ציון להעביר את ה-ACE בירושה לקבצים תחתיה, ו-(CI) להעביר בירושה לתיקיות תחתיה. היקף הירושה הוא בעצם “מי יכול לקרוא את ה-dump”, ולכן לפני שמוסיפים אותה כדאי לוודא שוב שהיא לא סותרת את המדיניות שנקבעה בפרק 8.3.

זרימת בדיקת ה-ACL של DumpFolderתרשים שמראה שבשירותים ותהליכים עם הפרדת הרשאות קל שהכתיבה תיכשל בשקט, ולכן בודקים את ה-ACL הנוכחי עם icacls, ואם צריך מוסיפים לחשבון ההרצה הרשאת שינוי עם ירושה, ומתאימים את היקף הירושה למדיניות הצפייה.לא יכוליכולבודקים את ה-ACL הנוכחי עם icaclsחשבון ההרצה יכול לכתוב?מוסיפים הרשאת שינוי עם ירושהממשיכים כמו שהואמתאימים את היקף הירושה למדיניות הצפייה

איור 14: בדיקת יכולת הכתיבה ובדיקת מי יכול לקרוא נעשות באותו מקום.

10.3 להמשיך להוציא full dump ישירות לכונן המערכת בייצור

זו תקלת נפח קלאסית. מגבילים מראש מספר שמורים ומפרידים את יעד הפלט.

10.4 לנסות לראות גם hang רק עם WER

‏WER LocalDumps חזק בעיקר לקריסות. יש מצבים שבהם ‏hang ו-first chance exception מתאימים יותר ל-ProcDump.

10.5 להשאיר -e 1 פעיל תמיד ולהיגרר לסופת חריגות

‏first chance exception נוח, אבל בדרך כלל יש הרבה מהם. מציאותי להגביל את הכמות, להשאיר פעיל לזמן קצר, ולהגביל את היעד.

11. סיכום

‏crash dump הוא נקודת תצפית חזקה מאוד עבור תקלות עם שיעור שחזור נמוך. בפרט באפליקציית Windows שבה מעורבים COM,‏ P/Invoke, DLL נייטיבי או הרצה ארוכה, יש ערך בכך שקובעים מראש “מה נשאר כשזה נופל”.

הסדר המומלץ פשוט.

  1. קודם מכניסים WER LocalDumps לפי אפליקציה
  2. מוסיפים ProcDump אם צריך
  3. אם רוצים שליטה נוספת, משתמשים ב-MiniDumpWriteDump בהנחה של תהליך נפרד

אם מתקדמים בסדר הזה, קשה לטעות בגדול.

12. מקורות

  • [ユーザーモード ダンプの収集 - Win32 apps Microsoft Learn](https://learn.microsoft.com/ja-jp/windows/win32/wer/collecting-user-mode-dumps)
  • [ProcDump v11.1 - Sysinternals Microsoft Learn](https://learn.microsoft.com/en-us/sysinternals/downloads/procdump)
  • [MiniDumpWriteDump function (minidumpapiset.h) - Win32 Microsoft Learn](https://learn.microsoft.com/en-us/windows/win32/api/minidumpapiset/nf-minidumpapiset-minidumpwritedump)
  • [User-mode dump files - Windows drivers Microsoft Learn](https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/user-mode-dump-files)
  • [ユーザー モード ダンプ ファイルの分析 - Windows drivers Microsoft Learn](https://learn.microsoft.com/ja-jp/windows-hardware/drivers/debugger/analyzing-a-user-mode-dump-file)
  • [Windows デバッガーをインストールする - Windows drivers Microsoft Learn](https://learn.microsoft.com/ja-jp/windows-hardware/drivers/debugger/)
  • [Symbol path for Windows debuggers - Windows drivers Microsoft Learn](https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/symbol-path)
  • [!analyze (WinDbg) - Windows drivers Microsoft Learn](https://learn.microsoft.com/en-us/windows-hardware/drivers/debuggercmds/-analyze)
  • [Troubleshoot processes by using Task Manager - Windows Server Microsoft Learn](https://learn.microsoft.com/en-us/troubleshoot/windows-server/support-tools/support-tools-task-manager)
  • [Enabling Postmortem Debugging - Windows drivers Microsoft Learn](https://learn.microsoft.com/en-us/windows-hardware/drivers/debugger/enabling-postmortem-debugging)
  • [MINIDUMP_TYPE enumeration (minidumpapiset.h) - Win32 Microsoft Learn](https://learn.microsoft.com/en-us/windows/win32/api/minidumpapiset/ne-minidumpapiset-minidump_type)
  • [icacls - Windows commands Microsoft Learn](https://learn.microsoft.com/en-us/windows-server/administration/windows-commands/icacls)
  • [NotMyFault - Sysinternals Microsoft Learn](https://learn.microsoft.com/en-us/sysinternals/downloads/notmyfault)

מאמרים עדכניים עם אותן תגיות, להעמקה בנושאים קרובים.

העמודים האלה ממקמים את הנושא בהקשר רחב יותר של שירותים והחלטות.

המאמר קשור ישירות לשירותים הבאים.

שאלות נפוצות

שאלות נפוצות בפניות בנושא המאמר.

מה זה crash dump? מה אפשר ללמוד ממנו?
זהו שמירה לקובץ של מצב התהליך ברגע הקריסה - כמו תצלום סטילס מזירת תאונה. אפשר לבדוק בדיעבד את קוד החריגה, את ה-thread שקרס ואת מחסנית הקריאות שלו, את המודולים שהיו טעונים, ובהתאם לכמות הזיכרון שנכלל אף את תוכן האובייקטים ב-heap. מצד שני, ציר הזמן שהוביל לשם, והמצב החיצוני של תקשורת וציוד, נוטים להיות חסרים - ולכן בפועל משלבים dump עם לוגים ו-heartbeat.
איפה מגדירים את LocalDumps של WER?
מגדירים תחת מפתח הרישום HKLM\SOFTWARE\Microsoft\Windows\Windows Error Reporting\LocalDumps. בפועל נוח יותר לרכז את ההגדרה במפתח משנה לפי אפליקציה, כמו MyApp.exe, ולא בהגדרה גלובלית. שלושת הערכים שכדאי לבדוק ראשונים הם DumpFolder ליעד הפלט, DumpCount למספר השמורים, ו-DumpType לסוג ה-dump - כך אפשר להשאיר dump מקומי אחרי קריסה בלי להפיץ כלי נוסף.
כדאי לבחור minidump או full dump?
קו מנחה: במחשבי פיתוח ובדיקה - full dump (‏DumpType=2), ובסביבת הלקוח - בוחרים minidump (‏DumpType=1) או full dump לפי היקף וצרכי סודיות. כשיש חשד להשחתת זיכרון, DLL נייטיבי, COM,‏ P/Invoke, או תקלת מצב אחרי הרצה ארוכה, עדיף לנטות לכיוון full. עם זאת, ה-full dump גדול בגודלו, ויש בו סיכון שמידע רגיש כמו connection string או token יתערב, ולכן צריך לקבוע מראש מיקום אחסון, מספר שמורים והרשאות גישה.
מתי משתמשים ב-ProcDump?
מכיוון ש-WER LocalDumps מיועד בעיקרו לקריסות, ProcDump מתאים כשרוצים לראות גם hang או first chance exception, כשרוצים להימנע ממצב קבוע ברישום, או כשרוצים לנטר רק תהליך שכבר רץ. האפשרויות האופייניות הן -ma ל-full dump,‏ -e לאיסוף בחריגה לא מטופלת,‏ -h לזיהוי hang, ו-w להמתנה להפעלה. -e 1 שמכוון ל-first chance exception נוטה לייצר כמות גדולה, ולכן מציאותי להשתמש בו לזמן קצר ומוגבל, עם הגבלת -n.

פרופיל הכותב

עמוד היכרות עם כותב המאמר.

Go Komura

מנהל KomuraSoft LLC

מתמחה בפיתוח תוכנה עבור Windows, ייעוץ טכני וחקירת תקלות, בעיקר בפרויקטים עם מערכות קיימות ובאגים שקשה לשחזר.

קישורים ציבוריים

חזרה לבלוג