سؤال

هذا السؤال يوفر المزيد من الوضوح على المشكلة الموضحة هنا.قمت بالمزيد من التحقيقات وجدت أن كومة الفك لا يحدث في الجزء التالي من التعليمات البرمجية:

class One
{
public:
    int x ;
};

class Wrapper
{
public:
    Wrapper(CString csText):mcsText(csText)
    {
        CString csTempText;
        csTempText.Format("Wrapper constructor :: %s\n", mcsText);
        OutputDebugString(csTempText);
    }

    ~Wrapper()
    {
        CString csTempText;
        csTempText.Format("Wrapper destructor :: %s\n", mcsText);
        OutputDebugString(csTempText);
    }
    CString mcsText;
};
class Test
{
    public:

    void notifyError()
    {
        try
        {
            int x = 10; 
        }
        catch(...)  {}
    }

    void OnRecvBuffer()
    {
        try
        {
            Wrapper a("AddRef");    
            One* p = NULL;
            p->x = 10;
        }
        catch(...)
        {
            notifyError();
        }   
    }   
};



int main() 
{
    Test* pTest = new Test;

    pTest->OnRecvBuffer();

    OutputDebugString("Test");
}

لقد جمعت هذه التعليمات البرمجية باستخدام VC6 حزمة الخدمة SP5 مترجم والإخراج هو "مجمع المنشئ ::AddRef!!!" (أيالمدمر من المجمع الكائن الذي شيد على كومة لا يسمى.هل هذا هو السلوك المتوقع ?أو هو علة مع VC ومترجم ؟ هل يمكنني استخدام بعض الأعلام المترجم بحيث كومة الفك يحدث في هذه الحالة ؟

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

المحلول

إذا كنت تريد استخدام SEH، يجب عليك استخدام _set_se_translator وظيفة والخيار مترجم / EHA.

نصائح أخرى

C++ القياسية لا يعطي أي شيء في حالة السلوك غير معرف.حتى لو MS لا.هذا هو منصة محددة شيء فالحذر الحذر.بعض هذه النقطة العائمة الاستثناءات يتم تشغيل Win32 الاستثناءات التي يمكنك محاولة للقبض مع _set_se_translator().المشكلة يمكنك التقاط Win32 استثناءات لكن المكدس الخاص بك لن يتم المساس بها بشكل صحيح.على الأقل هذا ليس شيئا يمكنك أن تراهن على حياتك.حيث يكمن في عدم جدوى ممارسة الرياضة.

تحديث:يتم طرح استثناء عمدا للتحقق من كومة الفك.السؤال هو لماذا المجمع الفئة المدمر هو عدم الحصول على ما يسمى.– نافين

إذا كان هذا هو الحال -- لا تفعل ذلك.هناك طرق أفضل في رمي الاستثناءات من خلال السلوك غير معرف.

E. g:

void OnRecvBuffer()
{
    try
    {
        Wrapper a("AddRef");    
        throw 42; // this'll throw an exception without invoking UB
    }
    catch(...)
    {
        notifyError();
    }
}

لا يمكنك إلغاء مرجعية NULL pointer.وأنت تحتج السلوك غير معرف هنا:

One* p = NULL;
p->x = 10;

بعد أن خط كل الرهانات و يمكن أن قتل لنا جميعا ;)

p هو مؤشر إلى One الكائن.يجب أن تحتوي على عنوان One الكائن.يجب تهيئة 0 -- لا يوجد كائن في العنوان 0.0 ليس عنوانا صالحا لأي كائن (هذه هي مضمونة من قبل قياسي).

ولأن استثناء منتظم C ++ لا يعالج هذا النوع من الاستثناء، لديك لاستخدام SEH الذي لا يعرف شيئا عن التطبيق وليس استرخاء.

وهذا هو سلوك غير معرف:

One* p = NULL;
p->x = 10;

وعند هذه النقطة التطبيق المجاني لتحطم الطائرة بدون الفك المكدس.
إذا كنت ترغب في اختبار كومة الفك استبدال هذا مع:

 throw 42; // Life the Universe and Everything thrown away

ويجب أن لا حيوي تخصيص كل ما تبذلونه من objcts هذا هو C ++ ليس جافا!

int main() 
{
    Test    pTest;   // Note the lack of new!

    pTest.OnRecvBuffer();

    OutputDebugString("Test");
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top