Cannot evaluate expression because a thread is stopped at a point where garbage collection is impossible, possibly because the code is optimized - can be caused by Large function calls
בעיית design/debugging מרגיזה, שנתקלתי בה בעבר:
נתון קוד קיים, שעובד ב production והיה צורך להוסיף פונקציונליות.
ע"מ לחקור את הפונקציונליות הקיימת הרצתי debugger , בשלב מסוים, לאחר כניסה אל פונקציה מסוימת, ה debugger השתגע - בחלון ה watch לא הראה יותר אובייקטים, אלא רק את ההודעה הבאה:
"Cannot evaluate expression because a thread is stopped at a point where
garbage collection is impossible, possibly because the code is optimized."
חיפושים בגוגל החזירו בעיקר מידע על
Funceval שלא ממש עוזר במקרה הזה.
הבעיה נבעה מ struct
ענק שהועבר כפרמטר לפונקציה,
כיוון ש struct הוא
ValueType - הוא גרם לניפוח של הגודל של הפרמטרים שעוברים לפונקציה - דבר שגרם להתרסקות של ה debugger.
את הסיבה לבעיה מצאתי (בקושי רב) בלינק הזה - בקצרה לפי מיקרוסופט:
"...generally speaking, when the total size of the arguments
passed to a callee function is larger than 256 bytes,
JIT will make the caller function partially interruptible.
In a partially interruptible code, not every location in the
code is a GC safe point. Therefore, it might be unsafe to
evaluate expression at certain locations.
When this happens you get [the error message]."
(כמובן שהבעיה יכולה גם לנבוע מפונקציה שמקבלת המווון פרמטרים).
struct אמור להיות קטן!! - לפי מיקרוסופט - "Unless you need reference type semantics, a class that is smaller than 16 bytes
may be more efficiently handled by the system as a struct."
במקרה הנדון ה struct נועד להעברת מספר די גדול של פרמטרים.
הפתרון במקרה שכזה אמור להיות שימוש ב class במקום struct להעברת כל הפרמטרים,ובדיקה האם אפשר לפצל את הלוגיקה כדי שלא ליצור פונקציה מפלצתית שתקבל המון פרמטרים.
מפאת חוסר זמן, ושימוש נרחב ב struct הנדון בפרוייקט (דבר שיצר בעיה בהפיכתו ל class), ה"פתרון" במקרה זה היה לשלוח את ה struct באמצעות ref כך מתבצע boxing שלו, והקריאה לפונקציה תופחת במשקל של פוינטר, ולא במשקל ה struct.
דרך אגב - במקרה של "פתרון" שכזה, צריך לוודא שלא משנים את ה struct בתוך הפונקציה - הוא הרי לא עובר יותר by value
שיהיה שבוע נפלא