שאלה על System.StackOverflowException ב - C#

susony

New member
שאלה על System.StackOverflowException ב - C#

שלום,
בניתי סימולציה לפרוייקט מחקרי שאני עושה, והיא נופלת עם ההערה שלמעלה. הפיתוח נעשה בעזרת studio.net 2010.
הסימולציה משתמשת המערך דו מימדי שעושה עליו חיפוש רקורסיבי, ורשימת מקושרת ששומרת עליה את הנתונים.
מכיוון שאני לא שולט לגמרי ביכולות של C#, אני לא משתמש האובייקט של רשימה מקושרת של המערכת, אלא בונה אותה בעצמי.

אני מבין שהבעיה היא זליגת זיכרון.
אני לא לגמרי מבין איך GC עובד, ניסיתי להפעיל אותו, אבל לא נראה לי שזה עזר לי.


כמו כן עקבתי אחרי התוכנית דרך ה-task manager, ונראה שהתוכנית צורכת כ- 8-9MB לכל אורכה, גם כשהיא נופלת היא לא עוברת את ה-10MB, כך שנראה שאין ממש זלעגת זיכרון.

אשמח לכל עזרה שתינתן
אביב
 

susony

New member
יש לי תנאי עצירה,

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

vinney

Well-known member
רקורסיה וStackOverflowException

זה די ברור הרי, לא? הרקורסיה שלך עמוקה מדי. תממש אותה באופן איטרטיבי.
 

susony

New member
האם אני יכול להגדיל את עומק הרקורסיה המותר?

מה זה מימוש איטרטיבי?
לולאות?
 

vinney

Well-known member
כן, לולאות.

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

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

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

susony

New member
יש לך מושג מה גודלהמחסנית המקסימלי האפשרי?

וכמה יש לי בהגדרות DEFAULT?

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

vinney

Well-known member
כמו שאמרתי - זה בכלל לא משנה

עכשיו זה נתקע לך כשהמערך כולל 200 איברים (לדוגמא), תכפיל את המכסנית - זה יפול על 400 איברים. זה לא משנה מה תעשה עם המחסנית, ברגע שהרקורסיה שלך מגיעה לכאלה עמקים אתה תיפול.
 

susony

New member
אתה יכול לתת יותר הסבר?

או שעדיף שאמצא חומר לקרוא על זה?
 
ההסבר הוא בקוד.

class Program
{
static int s_depth;

static void Main()
{
// GetRecursionDepth_();
var t = new Thread(GetRecursionDepth_, 1000000000);
t.Start();
t.Join();
}

static void GetRecursionDepth_()
{
Console.SetCursorPosition(0, 0);
Console.Write(s_depth++);
GetRecursionDepth_();
}
}
 

nocgod

New member
הבעיה שלך...

ש:
א. לא צירפת קוד שנוכל לראות
ב. שאתה משתמש במבני נתונים קלאסיים שאתה כותב כשיש לך מבני נתונים מצויינים שבאים עם #C (ובשילוב עם linq זה בכלל אגדה)
ג. אתה צריך להבדיל בין גודל הstack לבין כמות הזיכרון שכל frame ב stack לוקח - התוכנית לא צריכה לקחת הרבה זיכרון (אני יכול להפיל אותה עם פחות זיכרון) היא פשוט צריכה הרבה קריאות מכוננות.
ד. GC עובד בצורה אוטומטית - לרוב אין צורך לקרוא לו - אולי אם יש צרכים מיוחדים אפשר לשנות לו את הpolicy (נגיד כמו בג'אווה)
 

susony

New member
תודה על העזרה

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

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

3. קשה לי להגיד מהו עומק הרקורסיה, אבל עם המודל שלי, הוא יכול להגיע ל- 10,000 - 20,000 קריאת מכוננות, ואני צריך להגיע בהמשך להרבה יותר.

אם אתם אומרים שזה לא יעיל ועדיף לעשות את זה דרך לולאות, אני כנראה אעשה את זה.

אשמח לעצה
 

susony

New member
אולי עוד מילה על האלגוריתם

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

nocgod

New member
אז תבנה ממנה גראף ותנסה לעבוד על הגראף

אולי אז לא תצטרך לשבור את הראש עם רקורסיות, כמובן אם לייצוג של גראף יש הגיון בבעיה שלך
לגראפים ורשתות אני ממליץ על ספריית JUNG (בג'אווה), מכילה לא רק מימושים לגראפים אלא גם אלגוריתמים לעבודה עם גראפים ורשתות זרימה
 

susony

New member
תודה על ההמלצות,

זה תחום שאני לא כל כך מכיר, אבל יכול להיות שיש שם פתרון לבעיה שלי, לפחות לבעיות מורכבות יותר.

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

nocgod

New member
קח גם בחשבון שמוניפולציות של מטריצות

הן פעולות יקרות ותמיד עדיף להשתמש עם ספריות בדוקות שנכתבו על ידי קבוצות מחקר ונמצאות תחת תחזוקה
לצורך העניין באחד החלקים בפרוייקט שלי יש צורך לעשות פירוק SVD למטריצות ענק (1200 על 72000), בוא נגיד שזה פעולה לא זולה
ולא הייתי רוצה לממש לבד את פירוק הSVD מאחר וקרוב לוודאי לא הייתי מממש את זה בצורה כל כך מקצועית כמו שנגיד זה מומש ב JAMA
אגב לאט לאט צצות להן ספריות ו wrappers לספריות מתמטיות (בעיקר תחום המתמטיקה הלינארית) שמשתמשות בכרטיסי מסך (CUDA) כדי לחשב את זה
הרי זה למה שכרטיסי מסך יועדו :)
 

susony

New member
החוזק של מטלב היא בעבודה בפתרון בעיות

לא כל כך מניפולציות על מערכים. אני לא כל כך משתמש בכלים היחודיים של מטלב עבור הסימולציה הזו, צורת התכנות שלי במטלב עבור הסימולציה הזו לא שונה מהותית מצורת התכנות שלי ב-C#.

הפעם האחרונה שעבדתי עם מטלב היתה לפני כ-5 שנים, ואז ראיתי הבדל בזמני הריצה בין תכנות ב-C++ (שאז עבדתי איתו) לתכנות במטלב.
מכיוון שזמני הריצה מאד ארוכים, העדפתי לעבוד ב-C++.

היום אני חוזר לנושא הזה התחלתי ישר עם C#, שנראה לי יותר נוח מ-C++.

יכול באמת להיות שב-5 שנים האחרונות מטלב השתפרו בזמני הריצה שלהם.
 
טיעון מעניין.

אגב, עומק הרקורסיה הדיפולטי במטלב 500, ב-#C לפחות 86008. ובכל זאת, במטלב לא נתקלת בבעייה?
 
למעלה