سؤال

أحصل على NullReferenceException عند تشغيل تطبيق My متعدد الخيوط، ولكن فقط عند تشغيل وضع الإصدار خارج المصحح. يتم تسجيل تتبع المكدس، كما أنه يشير دائما إلى نفس مكالمة الوظيفة. أضع العديد من بيانات التسجيل في الوظيفة لمحاولة تحديد المسافة التي ستحصل عليها، ويتم تسجيل كل عبارة، بما في ذلك واحدة في السطر الأخير من الوظيفة. ما هو مثير للاهتمام هو أنه عند حدوث NullReferenceException، لا يتم تسجيل البيان بعد استدعاء الوظيفة:

    // ...
    logger.Log( "one" );  // logged
    Update( false );
    logger.Log( "eleven" );  // not logged when exception occurs
}

private void Update( bool condition )
{
    logger.Log( "one" );  // logged
    // ...  
    logger.Log( "ten" );  // logged, even when exception occurs
}

لا يحدث الاستثناء في كل مرة يتم استدعاء الوظيفة. هل من الممكن أن تكون المكدس تالفة إما قبل أو أثناء تنفيذ الوظيفة بحيث يتم فقد عنوان المرسل، مما يؤدي إلى مرجع فارغ؟ لم أكن أعتقد أن هذا النوع من الأشياء ممكنة تحت .NET، لكنني أعتقد أن الأمور الغريبة قد حدثت.

حاولت استبدال المكالمة إلى الوظيفة بمحتويات الوظيفة، لذلك يحدث كل شيء مضمون، ثم يحدث الاستثناء عند خط يبدو وكأنه هذا:

foreach ( ClassItem item in classItemCollection )

لقد تحققت من خلال تسجيل من خلال تسجيل أن "classitemcollection" ليست فارغة، وأجربت أيضا تغيير ما حدث إلى أ ل في حالة قيام Ienumerator بعمل شيء مضحك، ولكن يحدث الاستثناء في نفس السطر.

أي أفكار حول كيفية التحقيق في ذلك أكثر؟

تحديث: اقترح العديد من المستجيبين حلولا محتملة لها علاقة مع التأكد من أن المسجل ليس فارغا. لتكون واضحة، تمت إضافة بيانات التسجيل لأغراض تصحيح الأخطاء بعد بدء الاستثناء يحدث.

هل كانت مفيدة؟

المحلول

لقد وجدت مرجعي فارغ. مثل فريدريك وميكانيا اقترح، لم أقدم معلومات كافية للمجتمع لإيجاد حل، لذلك احسب أنني يجب أن نشر ما وجدته فقط لوضع هذا للراحة.

هذا هو تمثيل ما كان يحدث:

ISomething something = null;

//...

// the Add method returns a strong reference to an ISomething
// that it creates.  m_object holds a weak reference, so when
// "this" no longer has a strong reference, the ISomething can
// be garbage collected.
something = m_object.Add( index );

// the Update method looks at the ISomethings held by m_object.
// it obtains strong references to any that have been added,
// and puts them in m_collection;
Update( false );

// m_collection should hold the strong reference created by 
// the Update method.
// the null reference exception occurred here
something = m_collection[ index ];

return something;

تحولت المشكلة إلى أن يكون استخدامي لمتغير "شيء" كمرجع قوي مؤقت حتى يتم الحصول على طريقة التحديث واحدة دائمة. التحويل البرمجي، في وضع الإصدار، يحسن بعيدا "شيء = m_object.add ()؛ التعيين، لأن "شيء ما" لا يتم استخدامه حتى يتم تعيينه مرة أخرى. سمح هذا بأنه يتم جمعه Isomething القمامة، لذلك لم تعد موجودة في m_collection عندما حاولت الوصول إليها.

كل ما كان علي فعله هو ضمان احتجاز مرجع قوي إلا بعد الدعوة إلى التحديث.

أنا مشكوك فيه أن هذا سيكون من أي استخدام لأي شخص، ولكن في حالة كان أي شخص فضولي، لم أكن أرغب في ترك هذا السؤال دون إجابة.

نصائح أخرى

حقيقة أنه يسجل "عشرة" سيجعلني أبحث أولا في:

  • هو logger من أي وقت مضى ... هل هذا ربما أصبحت فارغة بطريقة أو بأخرى
  • هو الخطأ في الداخل Log بحد ذاتها

من الصعب أن أقول دون سياق ما يكفي من ذلك - ولكن هذه هي الطريقة التي كنت أستكملها. يمكنك أيضا إضافة بسيطة null اختبار في مكان ما؛ كهدوء صفيق، يمكنك إعادة تسمية Log طريقة لشيء آخر، وإضافة طريقة تمديد:

[Conditional("TRACE")]
public static void Log(this YourLoggerType logger, string message) {
    if(logger==null) {
       throw new ArgumentNullException("logger",
            "logger was null, logging " + message);
    } else {
       try {
           logger.LogCore(message); // the old method
       } catch (Exception ex) {
           throw new InvalidOperationException(
                "logger failed, logging " + message, ex);
       }
    }
}

يجب أن يسمي الرمز الحالي الجديد Log طريقة التمديد، والاستثناء سيجعل من الواضح تماما من أين هو بارز. ربما تغييرها مرة واحدة ثابتة ... أو ربما اتركها.

توافق ث / فريدريك - مزيد من التفاصيل ضرورية. مكان واحد ربما البدء في البحث: تذكر تطبيق متعدد الخيوط والخطأ الذي يحدث في الإصدار ولكن ليس تصحيح. قد تعمل في مشكلة توقيت مع مؤشرات الترابط متعددة التي تصل إلى نفس مراجع الكائنات.

بغض النظر، من المحتمل أن أضع:

Debug.Assert(classItemCollection != null);

مباشرة قبل التكرار الحلقة. لن يساعدك في وضع الإصدار، ولكن قد يساعدك في قبض المشكلة إذا كان (متى؟) يحدث في تصحيح الأخطاء.

كنت أبحث عن رمز يضع مسجل أو أحد معاليها إلى NULL. هل هناك خصائص مسجل، عند تعيينها إلى NULL، قد تؤدي إلى ذلك؟ يسرع وضع الإصدار في بعض الأحيان لتنفيذ التطبيق الذي يمكن أن تكشف عن مشكلات المزامنة التي يتم ملثمين بواسطة عقوبة الأداء لوضع التصحيح و / أو المصحح.

حقيقة أن "أحد عشر" لا يتم تسجيل الدخول يؤدي لي إلى الاعتقاد بأن المسجل يجري تعيينه إلى NULL قبل إجراء هذه المكالمة. يمكنك أن تلتفها في محاولة / الصيد ومعرفة ما إذا كان يضرب الجزء الصيد من الكتلة؟ ربما يمكنك إدراج MessageBox.Show أو كتابة شيء إلى ملف معروف عند حدوث ذلك.

هل تقوم بتعديل classitemcollection من مؤشرات الترابط متعددة؟ إذا قمت بتغيير المجموعة في مؤشر ترابط آخر، فقد يتم إبطال جهاز الكمبيوتر الذي قد يؤدي إلى استثناءك. قد تحتاج إلى حماية الوصول مع قفل.

تحرير: يمكنك نشر مزيد من المعلومات حول أنواع الطبقة الكلاسيكية والصفوفة؟

احتمال آخر هو أن Classitem هو نوع القيمة والكلورة Classitemcollection عبارة عن مجموعة عامة ويتم إضافتها بطريقة ما بطريقة ما إلى المجموعة. يلقي التالي nullreencexception:

        ArrayList list=new ArrayList();

        list.Add(1);
        list.Add(2);
        list.Add(null);
        list.Add(4);

        foreach (int i in list)
        {
            System.Diagnostics.Debug.WriteLine(i);
        }

هذه المشكلة بالذات يمكن حلها بواسطة INT؟ أنا أو كائن أنا في foreach أو استخدام حاوية عامة.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top