DCSIMG
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 - Avi Pinto

Avi Pinto

על הבלוג

Follow uberPinto on Twitter

View Avi Pinto's profile on LinkedIn

Subscribe in a reader Subscribe by Email

 


Two new sculptures

View my Air Brush Work at Avipinto.com

Helping a friend, great tool for fixing file names

JavaScript Tutorial


Disclaimer All postings/content on this blog are licensed under a Creative Commons Attribution By license and provided "AS IS" with no warranties, and confer no rights.
All entries in this blog are my opinion and don't necessarily reflect the opinion of my employer or sponsors.

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 
 
שיהיה שבוע נפלא

תוכן התגובה

Shlomo כתב/ה:

מעניין מאוד,

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

# March 15, 2009 10:54 AM

Rotem Bloom כתב/ה:

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

# April 1, 2009 1:23 PM

Noam כתב/ה:

You should still consider converting this struct to class and refactorying espcially when it has wide usage in your program as parameter. The 16 bytes rule comes from the overhead on putting the data on the stack back and forth...

# April 30, 2009 5:52 PM

Avi Pinto כתב/ה:

@Noam אתה צודק לחלוטין,

מה גם שזו שאלה שתעלה אצל כל מתכנת שיתקרב אל הקוד הזה - "למה לכל הרוחות שמו פה struct ואז העבירו אותו ב ref???" )

דבר שיגרור בזבוז זמן במקרה הטוב(הרי צריך לענות לו לא?:)),  

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

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

ה struct הזה הופיע בכל כך הרבה מקומות, שזו משימה שתיקח לא מעט זמן - לשנות ולבדוק שהכל בסדר.

# April 30, 2009 7:28 PM

spiritus asper כתב/ה:

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

# May 16, 2009 1:29 AM
שלח תגובה

(שדה חובה)  

(שדה חובה)  

(אופציונלי)

(שדה חובה) 

Please add 6 and 1 and type the answer here:


Enter the numbers above: