This is a mirror of official site: http://jasper-net.blogspot.com/

CLRStack -p" Isn't Always Reliable"

| Sunday, June 20, 2010
אחת הפקודות היותר שימושיות שזמינה לנו ב-SOS היא CLRStack!, שביחד עם הדגל p- מנסה להציג לנו את ערכי הפרמטרים שהועברו לכל פונקציה ב-Stack הדוט-נטי שלנו. אני אומר "מנסה" בגלל ש-SOS יציג לנו את הערכים רק אם  הוא חושב שהוא הצליח למצוא את הערכים הנכונים, ואני אומר "חושב" כי במקרים מסויימים הוא פשוט הולך לטעות. 

במקרה שבו SOS יגיע למסקנה שהוא לא יודע מה הערך שהועבר בפרמטר, תודפס התשובה <no data>. זה קורה בגלל שלעיתים ל-SOS אין באמת דרך לדעת בוודאות מה היה ערכו של הפרמטר שהועבר לפונקציה רק על ידי הסתכלות על מצב ה-Stack Frame הרלוונטי. במקרה שבו אנחנו משתמשים ב-Calling Convention כגון fast call, שני הפרמטרים הראשונים (מצד שמאל) שמבחינת הגודל מתאימים להכנס לתוך רג'יסטר, יועברו בתוך ECX ו-EDX במקום להיות מועתקים על המחסנית. עבור Member Functions למשל, ערכו של המצביע this נוהג לעבור בתוך ECX. ההתנהגות הזאת יכולה להוביל לכך שאם לקחנו Dump או עצרנו עם הדיבאגר בנקודה מאוחרת מדי בחיי התוכנית, יתכן שערכם של אותם פרמטרים שהועברו כרג'יסטרים כבר נדרסו. 
להבדיל ממקרים בהם SOS מגיע למסקנה שהוא לא בטוח מה היה ערכו של הפרמטר, מדי פעם הוא גם הולך פשוט לטעות ולהדפיס את הערכים הלא נכונים. מה שיכול כמובן להוביל ללא מעט כאב ראש אצל מי שמנסה לדבג את התוכנית (הופעה של ערכים "בלתי הגיוניים", קיום של Execution Paths "בלתי אפשריים" וכו'..) 
מה שיפה, זה שלא צריך להתאמץ יותר מדי כדי לגרום לעיוות כזה לבוא לידי ביטוי. ניקח את התוכנית הבאה כדוגמה: 

   class Program
   {
       static void Main(string[] args)
       {
           Foo a = new Foo();
           a.Work(1, 2, 3, 4, 5);
       }
   }

   class Foo
   {
       [MethodImpl(MethodImplOptions.NoInlining)]
       public void Work(int x, int y, int z, int k, int p)
       {
           // break with debugger here
       }
   }

Read more: Liran Chen's Blog

Posted via email from .NET Info

0 comments: