سؤال

يوضح التعليمة البرمجية التالية مشكلة غريبة عندي في Turbo C++ مستكشف المشروع.واحد من ثلاثة كومة الأجسام في د::د() لم تدمر بعد الخروج من نطاق.

يحدث هذا فقط إذا جمعت في وضع الإصدار ، auto_ptrs a_ و b_ من أنواع مختلفة استثناء طرح لا ترث من الأمراض المنقولة جنسيا::الاستثناء.يبدو أن تعمل على ما يرام في VC++ 2005 و C++ Builder 2009.لم تثبيت BDS2006 تحديث 2, مجموعة تحديثات الإصلاح العاجل الإصلاح العاجل 12.

هو قانون بلدي أو ومترجم ؟ هل تعرف من الإصلاح ؟ عدم القدرة على استخدام موثوق auto_ptr في VCL المشروع سيكون غير مريح جدا.


#include <memory>
#include <stdexcept>
#include <iostream>

typedef std::exception my_error; // will work fine if replaced with line below
//class my_error : public std::exception {};

class A {};
class B {};

class C
{
public:
    C(int id) : id_(id) { std::cout << "C::C() " << id_ << std::endl; };
    ~C() { std::cout << "C::~C() " << id_ << std::endl; };
private:
    int id_;
};

class D
{
public:
    D()
    {
        C c1(1);
        C c2(2);
        C c3(3);

        throw my_error();
    };

private:
    std::auto_ptr<A> a_;
    std::auto_ptr<B> b_; // will work fine if replaced with line below
//  std::auto_ptr<A> b_;
//  std::auto_ptr<C> c_; // see expected output
};

#pragma argsused
int main(int argc, char* argv[])
{
    try
    {
        D d;
    }
    catch (...)
    {
        std::cout << "caught exception" << std::endl;
    }

    return 0;
}


المتوقع:

C::C() 1
C::C() 2
C::C() 3
C::~C() 3
C::~C() 2
C::~C() 1
caught exception


حصلت:

C::C() 1
C::C() 2
C::C() 3
C::~C() 2
C::~C() 1
caught exception


حصلت (مع خط '// std::auto_ptr<C> c_;'uncommented):

C::C() 1
C::C() 2
C::C() 3
C::~C() 1
caught exception


تحرير: إجراء التغييرات المقترحة

تحرير 2:
لقد اختبرت ذلك مع C++ Builder 2007 (11.0.2902.10471) الذي يظهر نفس المشكلة.تكوين الإصدار يعمل بأسرع ما تحقق "تصحيح المعلومات" مربع في مشروع -> خيارات -> C++ Compiler -> التصحيح.يدهشني أن الملف القابل للتنفيذ يحصل أصغر مع "تصحيح المعلومات" تمكين (أسفل إلى 31.5 KB من 39.5 KB ).

تحرير 3:
في Turbo C++ Explorer (C++ Builder 2006) (10.0.2288.42451) تكوين الإصدار يعمل إذا كنت قم بإلغاء تحديد "المضمنة توسيع وظيفة (السادس)" مربع في مشروع -> خيارات -> C++ Compiler -> التصحيح.استبدال السطر الأول (#include <memory>) مع التعليمات البرمجية التالية يجعل من العمل أيضا.

#pragma option push -vi-
#include <memory>
#pragma option pop 
هل كانت مفيدة؟

المحلول

هذا ويبدو أن المترجم علة.جريت نفس العينة في VS2008SP1 وحصلت والمخرجات المتوقعة.

نصائح أخرى

أيا كان الأمر يستحق دول مجلس التعاون الخليجي 3.4.6 يفعل الشيء المتوقع:

$ g++ main.cpp

$ a.out
C::C()
C::C()
C::~C()
C::~C()
caught exception

إنه مترجم علة في C++Builder 2006.C++Builder 2009 إصلاحات ؛ هذا هو الناتج أحصل على نسخة v6.1:

C::C() 1
C::C() 2
C::C() 3
C::~C() 3
C::~C() 2
C::~C() 1
caught exception

إذا تم طرح استثناء في كائن منشئ ، المدمر سوف لا تعمل.

المترجم له أي وسيلة لمعرفة ما إذا كان منشئ الانتهاء بما فيه الكفاية بالنسبة المدمر لتشغيل بشكل صحيح.

انظر http://www.parashift.com/c++-faq-lite/exceptions.html#faq-17.4

تحرير:ردا على التعليق أدناه...في هذه الحالة, فإنه من المرجح مترجم علة الخلط 'لا تشغيل المدمر' القاعدة مع غير صحيح وليس تدمير الكائنات على المكدس.

ربما cout تيار لا مسح?يمكنك أن تجرب مع cerr بدلا من ذلك ؟ أو مباشرة ضع نقطة توقف في المدمر و تحقق مما إذا كانت الضربة ؟

لقد اختبرت هذا على الحرة فلكس bcc5.5.1 و C++ Builder 6 bcc5.64 و كلاهما يعمل كما هو متوقع-الذي هو مفاجأة النظر عن سنه.ثم حاولت في هذا C++ Builder عام 2007 ، bcc5.93 الخلل موجود هناك.في الواقع, على سبيل المثال رمز يمكن أن تكون مبسطة إلى البدائية أنواع الخلل قد تكون لا تزال موجودة:

class D
{
public:
    D();

private:
    std::auto_ptr<int>      a_;
    std::auto_ptr<short>    b_;
    std::auto_ptr<char>     c_;
    std::auto_ptr<bool>     d_;
};

هذا مثال متطرف ينتهي تسبب أيا من المقابلة المدمر هو أن يطلق على فئة C!إذا كنت مهتما في تشخيص هذا الخلل كذلك حيلة لك يمكن أن تؤدي إلى إدراج الجمعية توقف داخل D::D() المنشئ:

// Note that D::D() ctor can't be inlined if it contains assembly
// limitation of borland compilers unfortunately
D::D()
{
    __asm int 3;
    C c1(1);
    C c2(2);
    C c3(3);

    throw my_error();
}

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

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

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