דילוג לתוכן
  • דף הבית
  • קטגוריות
  • פוסטים אחרונים
  • משתמשים
  • חיפוש
  • חוקי הפורום
כיווץ
תחומים

תחומים - פורום חרדי מקצועי

💡 רוצה לזכור קריאת שמע בזמן? לחץ כאן!
  1. דף הבית
  2. תכנות
  3. בעיה מעניינת ב C#

בעיה מעניינת ב C#

מתוזמן נעוץ נעול הועבר תכנות
16 פוסטים 4 כותבים 294 צפיות
  • מהישן לחדש
  • מהחדש לישן
  • הכי הרבה הצבעות
התחברו כדי לפרסם תגובה
נושא זה נמחק. רק משתמשים עם הרשאות מתאימות יוכלו לצפות בו.
  • מנצפךמ מנותק
    מנצפךמ מנותק
    מנצפך
    כתב ב נערך לאחרונה על ידי
    #1

    ישנה איזושהי פקודה שזורקת שגיאה.
    אבל לא סתם שגיאה, אלא דברים שקשורים לקריאות API של ווינדוס,

    מה שמוזר, זה שאני נמצא במצב שאני בכלל לא קורא לשגיאה, אלא היא נמצאת בתוך תנאי שלא מתקיים!

    הנה הקטע קוד

                int i = 1;
         
                if (i==2)
                {
                    int y = int.Parse("s");
                    MessageBox.Show("any message");
                    someWindowsApiCall();
                }
    

    אתם יכולים לראות שהתנאי בכלל לא מתקיים, ובכל אופן, שורה 7 גורמת לקריסה.
    לא משנה כרגע מה הפונקציה הזאת עושה מאחורי הקלעים, (לצורך העניין היא יכולה, נניח, להשמיע צליל או לכבות את המסך או מה שתרצו), אבל היא בכלל לא אמורה להיקרא!

    אם אני מוחק את שורה 7, אין שום בעיה.

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

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

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

    ייתכן שזה קשור, וייתכן שבלבלתי בשכל.

    אשמח לתגובתכם.

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

    תגובה 1 תגובה אחרונה
    0
    • מנצפךמ מנותק
      מנצפךמ מנותק
      מנצפך
      כתב ב נערך לאחרונה על ידי מנצפך
      #2

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

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

      תגובה 1 תגובה אחרונה
      0
      • yossizY מנותק
        yossizY מנותק
        yossiz
        כתב ב נערך לאחרונה על ידי yossiz
        #3

        @מנצפך (אל תיקח מה שאני אומר ללב, אני גם הייתי במצבים כאלה בעבר)
        א. זה מאוד מאוד יומרני מצדך להאשים את הבאג בפריימורק/קומפיילר/מעבד... אני יכול לומר בכ-99.99% שמדובר בשגיאה שלך
        ב. האם אתה יכול לשחזר את הקוד שגורם את השגיאה בצורה תמציתית שנוכל לבדוק את זה?
        ג. הבאג המדובר במעבדי אינטל (המכונה spectre או meltdown ועוד ממשפחה זו שמקושרים ל-speculative execution) הוא נושא מתקדם, אי אפשר סתם כך לנצל את החולשה כי המעבד יודע לנקות אחריו בצורה טובה מאוד. עובדה שעברו עשרות שנים עד שהבינו שיש כאן חולשה, יש רק שאריות כמעט בלתי נראים שהמומחים מצאו דרך לזהות.
        ד. האם עשית נקודת עצירה על התנאי לוודות ב-100% שזה false?

        📧 יוסי@מייל.קום | 🌎 בלוג | ☕ קפה

        dovidD 2 תגובות תגובה אחרונה
        3
        • dovidD מנותק
          dovidD מנותק
          dovid ניהול
          השיב לyossiz ב נערך לאחרונה על ידי
          #4

          @yossiz אמר בבעיה מעניינת ב C#:

          ד. האם עשית נקודת עצירה על התנאי לוודות ב-100% שזה false?

          @מנצפך אמר בבעיה מעניינת ב C#:

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

          מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

          בכל נושא אפשר ליצור קשר dovid@tchumim.com

          תגובה 1 תגובה אחרונה
          4
          • dovidD מנותק
            dovidD מנותק
            dovid ניהול
            השיב לyossiz ב נערך לאחרונה על ידי
            #5

            @yossiz אמר בבעיה מעניינת ב C#:

            ב. האם אתה יכול לשחזר את הקוד שגורם את השגיאה בצורה תמציתית שנוכל לבדוק את זה?

            זה לא רק עבורנו.
            שכפול הבעיה היא תנאי חובה לכל תיאוריה וק"ו תשובה למה הבעיה קורית.

            מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

            בכל נושא אפשר ליצור קשר dovid@tchumim.com

            תגובה 1 תגובה אחרונה
            2
            • מנצפךמ מנותק
              מנצפךמ מנותק
              מנצפך
              כתב ב נערך לאחרונה על ידי
              #6

              אנסה לשתף קטע קוד תמציתי

              תגובה 1 תגובה אחרונה
              1
              • מנצפךמ מנותק
                מנצפךמ מנותק
                מנצפך
                כתב ב נערך לאחרונה על ידי
                #7
                using System;
                
                namespace TestProblem
                {
                    class Program
                    {
                        static void Main(string[] args)
                        {
                
                            int i = 1;
                
                            if (i == 2)
                            {
                                Console.WriteLine("THE CONDITION IS TRUE");
                                int x = TestProblem.Test;
                                int v = TestProblem.Test;
                            }
                            Console.ReadKey();
                        }
                    }
                
                    public class TestProblem
                    {
                        public static int Test = TestProblem.Get();
                        public static int Get()
                        {
                            Console.WriteLine("Before");
                            return 0;
                        }
                    }
                }
                
                
                1. אני מבין שזה קשור לאובייקט הסטטי במחלקה, שמשום מה הוא נוצר אפילו שהתנאי לא מתקיים.

                2. נא לשים לב שאם התנאי היה מתקיים, היה אמור להיות כתוב: "The condition is true"

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

                4)תנסו לכתוב במקום תנאי, ישירות את הערך false, ותיווכחו שהפונקציה לא נקראית

                dovidD 3 תגובות תגובה אחרונה
                1
                • dovidD מנותק
                  dovidD מנותק
                  dovid ניהול
                  השיב למנצפך ב נערך לאחרונה על ידי dovid
                  #8

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

                  הנה לשון התיעוד:

                  As is the case with all class types, the type information for a static class is loaded by the .NET runtime when the program that references the class is loaded. The program cannot specify exactly when the class is loaded. However, it is guaranteed to be loaded and to have its fields initialized and its static constructor called before the class is referenced for the first time in your program. A static constructor is only called one time, and a static class remains in memory for the lifetime of the application domain in which your program resides.
                  

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

                  מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

                  בכל נושא אפשר ליצור קשר dovid@tchumim.com

                  תגובה 1 תגובה אחרונה
                  3
                  • yossizY מנותק
                    yossizY מנותק
                    yossiz
                    כתב ב נערך לאחרונה על ידי
                    #9

                    @מנצפך
                    הכתבה הזאת מדבר בדיוק על הבעיה שלך:
                    https://csharpindepth.com/Articles/BeforeFieldInit
                    בינתיים לא קראתי לעומק אז אני לא יכול לסכם בקצרה בעברית.

                    📧 יוסי@מייל.קום | 🌎 בלוג | ☕ קפה

                    תגובה 1 תגובה אחרונה
                    3
                    • yossizY מנותק
                      yossizY מנותק
                      yossiz
                      כתב ב נערך לאחרונה על ידי
                      #10

                      עוד נקודה:

                      if (false) {
                        // do stuff...
                      }
                      

                      מוסר לגמרי מהקוד על ידי הקומפיילר. תבדוק ב-dnSpy ותווכח

                      📧 יוסי@מייל.קום | 🌎 בלוג | ☕ קפה

                      תגובה 1 תגובה אחרונה
                      4
                      • dovidD מנותק
                        dovidD מנותק
                        dovid ניהול
                        השיב למנצפך ב נערך לאחרונה על ידי dovid
                        #11

                        @מנצפך בקריאה חוזרת של מה שכתבת אני מבין שעד עכשיו היית מצפה אחרת:

                        1. אני מבין שזה קשור לאובייקט הסטטי במחלקה, שמשום מה הוא נוצר אפילו שהתנאי לא מתקיים.

                        זה ההיפך, ה"משום מה" הוא שזה קורה רק אם אתה מתייחס למחלקה (מן lazy כזה שלא טוענים מה שלא צריך) הפשטות של המושג סטטי אומרת שזה צריך לקרות ברגע טעינת האפליקציה.

                        מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

                        בכל נושא אפשר ליצור קשר dovid@tchumim.com

                        תגובה 1 תגובה אחרונה
                        1
                        • dovidD מנותק
                          dovidD מנותק
                          dovid ניהול
                          השיב למנצפך ב נערך לאחרונה על ידי dovid
                          #12

                          יאהוו לא שמתי לב לנקודה של הfalse זה באמת היה לי לחידה לולי @yossiz

                          מנטור אישי למתכנתים (ולא רק) – להתקדם לשלב הבא!

                          בכל נושא אפשר ליצור קשר dovid@tchumim.com

                          תגובה 1 תגובה אחרונה
                          3
                          • מנצפךמ מנותק
                            מנצפךמ מנותק
                            מנצפך
                            כתב ב נערך לאחרונה על ידי
                            #13

                            אוקי. מעניין מאוד.
                            כשיהיה זמן נתעמק בזה.

                            תגובה 1 תגובה אחרונה
                            0
                            • י מנותק
                              י מנותק
                              יוסף בן שמעון
                              כתב ב נערך לאחרונה על ידי
                              #14

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

                              yossizY 2 תגובות תגובה אחרונה
                              0
                              • yossizY מנותק
                                yossizY מנותק
                                yossiz
                                השיב ליוסף בן שמעון ב נערך לאחרונה על ידי yossiz
                                #15

                                @יוסף-בן-שמעון זה יכול להיות תלוי בגירסת ה-CLR.


                                תקציר הכתבה של jon skeet האגדי:

                                • ה-CLR תומך בשני סוגי איתחול סטטיים:
                                  • תזמון קשיח של האתחול: בדיוק ברגע של הגישה הראשונה לכל שדה או פונקציה (סטטי או לא) של המחלקה.
                                  • תזמון רופף (בדיקומפליזציה של המחלקה רואים שיש לו מאפיין: beforefieldinit), ה-CLR יכול לבחור אם ומתי לאתחל, יש רק הבטחה שזה יאותחל לפני הגישה הראשונה לשדה סטטי של המחלקה
                                    זה אומר שבפועל האתחול יכול לקרות יותר מוקדם או יותר מאוחר מבמקרה של תזמון קשיח.
                                • אם יש constructor סטטי, אז לפי ה-spec של #C הקומפיילר חייב להגדיר את זה כקשיח.

                                עכ"ד בקיצור

                                במקרה של @מנצפך מכיון שאין בנאי סטטי, המחלקה מוגדרת עם המאפיין beforefieldinit (אפשר לראות ב-dnSpy).
                                9bfcd574-798c-489e-ba27-05eca3ce1c24-image.png
                                מכיון שאין גישה בפועל לשדה סטטי של המחלקה (אולי לא במקרה האמיתי אבל לפחות בקוד הדוגמה), ה-CLR יכול לבחור לא לאתחל אותו בכלל, או לאתחל אותו בכל מקום בתוכנה שבא לו...

                                📧 יוסי@מייל.קום | 🌎 בלוג | ☕ קפה

                                תגובה 1 תגובה אחרונה
                                6
                                • yossizY מנותק
                                  yossizY מנותק
                                  yossiz
                                  השיב ליוסף בן שמעון ב נערך לאחרונה על ידי
                                  #16

                                  @יוסף-בן-שמעון אמר בבעיה מעניינת ב C#:

                                  אבל למעשה אני לא רואה שום דבר מודפס?

                                  @yossiz אמר בבעיה מעניינת ב C#:

                                  @יוסף-בן-שמעון זה יכול להיות תלוי בגירסת ה-CLR.

                                  מתברר שבדוטנט core הבנאי הסטטי לא נקרא בכלל, ובדוטנט רגיל זה כן נקרא

                                  📧 יוסי@מייל.קום | 🌎 בלוג | ☕ קפה

                                  תגובה 1 תגובה אחרונה
                                  2

                                  בא תתחבר לדף היומי!
                                  • התחברות

                                  • אין לך חשבון עדיין? הרשמה

                                  • התחברו או הירשמו כדי לחפש.
                                  • פוסט ראשון
                                    פוסט אחרון
                                  0
                                  • דף הבית
                                  • קטגוריות
                                  • פוסטים אחרונים
                                  • משתמשים
                                  • חיפוש
                                  • חוקי הפורום