मुझे एक टेस्ट केस मिला है जहां मेरे पास 3 सबोबजेक्ट्स (A
, B
और C
) के साथ एक कक्षा है, और दूसरा सबोबजेक्ट B
निर्माण के दौरान अपवाद फेंकता है। जैसा कि मैं सी ++ को समझता हूं, संकलक को बड़ी कक्षा के निर्माण को रिवाइंड करना चाहिए और पहली वस्तु A
को नष्ट करना चाहिए, लेकिन दूसरा (B
) या तीसरा (C
) ऑब्जेक्ट्स नहीं।इंटेल 2015 कंपाइलर बग, आरएआईआई विनाश सही नहीं है, क्या यह एक बग है या क्या मैं कुछ गलत कर रहा हूं?
क्या मैं देख रहा हूँ कि अगर मैं पहली वस्तु A
की "इन-वर्ग प्रारंभ", तो बजाय पहली वस्तु A
का उपयोग को नष्ट कर दिया हो रही है, 3 वस्तु C
नष्ट हो जाता है। बेशक यह बहुत खराब है जो किसी ऑब्जेक्ट को नष्ट करने के लिए नहीं बनाया गया है! यदि, उदाहरण के लिए, C
std:unique_ptr<T>
था, तो यह संभवतः एक कचरा संकेतक सिग्नल करेगा जब यह कचरा सूचक को मुक्त करने का प्रयास करता है।
यदि मैं पुराने स्कूल "सदस्य प्रारंभिकरण" का उपयोग करता हूं, तो यह समस्या नहीं होती है।
मैं कोड यह जीसीसी 4.8
के साथ इस दिखाई नहीं देता। वर्ग D
बग का खुलासा करता है। कक्षा E
में समान कार्य होना चाहिए, लेकिन यह बग का पर्दाफाश नहीं करता है।
#include <iostream>
using namespace std;
struct A {
A(const string& x) : x_(x) { cout << "A::A()" << (void*)this <<endl; }
~A() { cout << "A::~A() " << (void*)this<< endl;}
string x_;
};
struct B {
B(const A& a) { cout << "B::B()" << endl; throw "dead"; }
~B() { cout << "B::~B()" << endl;}
};
struct C {
C() { cout << "C::C()" << endl; }
~C() { cout << "C::~C()" << endl;}
};
struct D {
A a{"foo"}; // "new school In-class initialization"
B b{a};
C c;
D() { cout <<"D::D()" << endl; }
~D() { cout <<"D::~D()" << endl; }
};
struct E {
A a;
B b;
C c;
E()
:a{"foo"} // "old school member initialization"
,b(a)
{ cout <<"E::E()" << endl; }
~E() { cout <<"E::~E()" << endl; }
};
int main()
{
try {
D d;
}
catch(...)
{
cout << "got exception" << endl;
}
try {
E e;
}
catch(...)
{
cout << "got exception" << endl;
}
return 0;
}
यहां आउटपुट है। मुझे A
का निर्माण करने की उम्मीद है, B
आंशिक रूप से निर्मित तब फेंकता है, फिर A
नष्ट हो गया, लेकिन यह D
मामले के लिए मैं नहीं देखता हूं।
$ icpc -std=c++11 test.cpp
$ ./a.out
A::A()0x7fffe0a5ee90
B::B()
C::~C()
got exception
A::A()0x7fffe0a5eea0
B::B()
A::~A() 0x7fffe0a5eea0
got exception
- अद्यतन -
standard का वर्णन करता है कि क्या होना चाहिए की धारा 15.2.3
है किसी भी भंडारण अवधि जिसका प्रारंभ या के वर्ग प्रकार का ऑब्जेक्ट के लिए विनाश को अपवाद द्वारा समाप्त कर दिया जाता है, विनाशक प्रत्येक ऑब्जेक्ट के पूरी तरह से निर्मित सबोबजेक्ट्स के लिए आवेदक लगाया जाता है, अर्थात प्रत्येक सबोबजेक्ट के लिए प्रिंसिपल कन्स्ट्रक्टर (12.6.2) ने निष्पादन पूरा कर लिया है और विनाशक को अभी तक निष्पादन शुरू नहीं हुआ है, सिवाय इसके कि विनाश के मामले में, यूनियन जैसी कक्षा के संस्करण सदस्य नष्ट नहीं हुए हैं। उपरोक्त के निर्माण के रिवर्स ऑर्डर में उनके निर्माण को नष्ट कर दिया गया है। इस तरह के विनाश को पर किसी भी कार्यकर्ता-विनाशक के कार्य-प्रयास-ब्लॉक के हैंडलर में प्रवेश करने से पहले अनुक्रमित किया गया है।
उन है कि रुचि रखते हैं के लिए, एक 'कोशिश/catch' आवरण की उपस्थिति स्टैक में एक फर्क नहीं पड़ता और वहाँ compilers में विसंगतियों हैं: http://stackoverflow.com/questions/22137693/ देखना अगर-प्रारंभिक-या-विनाश-समाप्त हो गया है-अपवाद-जो-हाथ नहीं है –