2012-08-25 14 views
5

मुझे आश्चर्य है कि अगर कोई सी ++ गुरु वहां इस अजीब स्थिति पर कुछ प्रकाश डाल सकता है। बॉक्स 2 डी भौतिकी इंजन के साथ आने वाले उदाहरणों में से एक संदेश "शुद्ध आभासी विधि" नाम से क्रैश हो रहा है, लेकिन केवल एक निश्चित संकलक (और केवल रिलीज निर्माण में) के साथ।स्टैक फ्रेम के भीतर बार-बार इनलाइन कन्स्ट्रक्टर "शुद्ध वर्चुअल विधि" कहा जाता है?

जैसा कि आप जानते हैं बॉक्स 2 डी कोड का एक बहुत ठोस हिस्सा है, इसलिए मुझे लगता है कि यह संकलक के साथ एक समस्या हो सकती है, विशेष रूप से यह केवल यह विशेष संकलक के साथ होता है। मैं Windows7 पर mingw32 उपयोग कर रहा हूँ:

> gcc.exe --version 
gcc version 4.4.0 (GCC) 

नीचे Box2D के प्रासंगिक भागों का एक कट नीचे अंश है। प्लेसमेंट क्लोन समारोह में नए

b2Shape.h
b2CircleShape.h
b2CircleShape.cpp
SensorTest.h

//base class 
class b2Shape 
{ 
public: 
    virtual ~b2Shape() {} 
    virtual b2Shape* Clone(b2BlockAllocator* allocator) const = 0; 
}; 


//sub class 
class b2CircleShape : public b2Shape 
{ 
public: 
    b2CircleShape(); 
    b2Shape* Clone(b2BlockAllocator* allocator) const; 
}; 

inline b2CircleShape::b2CircleShape() {} 

b2Shape* b2CircleShape::Clone(b2BlockAllocator* allocator) const 
{ 
    void* mem = allocator->Allocate(sizeof(b2CircleShape)); 
    b2CircleShape* clone = new (mem) b2CircleShape; 
    *clone = *this; 
    return clone; 
} 

ध्यान दें: आप में पूर्ण स्रोत की जाँच कर सकते हैं।

अब निष्पादन है कि समस्या का कारण बनता है यह करने पर निर्भर करता:

{ 
    b2CircleShape shape; 
    shape.Clone(allocator); //ok 
} 
{ 
    b2CircleShape shape; 
    shape.Clone(allocator); //"pure virtual method called" 
} 

कैसे एक आभासी विधि कभी पहली जगह में कहा जा सकता है पर अपने आप को शिक्षित करने के बाद, मैं क्यों इसे यहाँ हो रहा था यह पता लगाने की कोशिश की , क्योंकि यह बेस क्लास कन्स्ट्रक्टर में वर्चुअल फ़ंक्शन को कॉल करने के क्लासिक केस में फिट नहीं है। अंधेरे के चारों ओर ठोकर खाने के लंबे सत्र के बाद मैं ऊपर के न्यूनतम मामले के साथ आया था।

मेरा जंगली अनुमान यह है कि संकलक यह देखने के लिए पर्याप्त स्मार्ट है कि इन दो b2CircleShape उदाहरण एक ही दायरे में उपयोग में नहीं हैं, इसलिए यह केवल एक के लिए स्थान आवंटित करता है और इसका पुन: उपयोग करता है। पहले उदाहरण के विनाश के बाद, vtable अपेक्षित है, hosed। फिर किसी कारण से जब दूसरा उदाहरण बनाया गया है, तो vtable फिर से नहीं बनाया गया है ...?

मैं समस्या से बचने वाली दो चीजों के साथ आया, लेकिन जैसा कि मैंने कहा है कि यह एक कंपाइलर समस्या की तरह लगता है, इसलिए मैं यह सुझाव नहीं दे रहा हूं कि इस कोड को बदलने की जरूरत है।

बेसियस फिक्स नंबर 1 बेस क्लास में आभासी विनाशक परिभाषा को टिप्पणी करना है। इस विषय पर मैंने जो सारी जानकारी पढ़ी है, वह बताती है कि यह जवाब नहीं है। (दिलचस्प बात यह है कि मुझे लगता है कि बेस क्लास विनाशक से 'आभासी' संशोधक को हटाने के लिए पर्याप्त नहीं था। मेरी समझ यह है कि संकलक डिफ़ॉल्ट डिस्ट्रक्टर ~ b2Shape() {} प्रदान करेगा यदि कोई निर्दिष्ट नहीं किया गया था, तो परिणाम अलग क्यों है अगर मैं वास्तव में निर्दिष्ट करता हूं कि डिफ़ॉल्ट क्या होगा? अच्छा, यह वास्तव में बिंदु के बगल में है ...)

मुझे पता नहीं था कि उप-वर्ग कन्स्ट्रक्टर से 'इनलाइन' को निकालने के लिए मुझे पता नहीं था । शायद प्लेसमेंट नए, इनलाइन निर्माण और उसी स्टैक फ्रेम में पुन: उपयोग किए गए उदाहरणों के बारे में कुछ है जो अच्छी तरह से एक साथ नहीं खेलता है। (अद्यतन: आगे की जांच प्लेसमेंट को अप्रासंगिक होने के लिए नया दिखाती है)

कुछ और शोध मुझे बताते हैं कि संकलक 'इनलाइन' सुझावों के बारे में जो कुछ भी पसंद करता है उसे करने के लिए स्वतंत्र है, इसलिए शायद अन्य कंपेलरों को यह समस्या नहीं है क्योंकि वे 'इनलाइन' को अनदेखा कर रहे हैं?

+0

क्या आप हमें दिखा सकते हैं कि वास्तव में आवंटक क्या है? क्या आप क्लोन फ़ंक्शन के मूल्य से आवंटक पास करने के किसी भी मौके से हैं? – Arunmu

+0

स्रोत यहां पाया जा सकता है। http://code.google.com/p/box2d/source/browse/trunk/Box2D/Box2D/Common/ ऐसा लगता है कि आवंटक अप्रासंगिक है क्योंकि मैं क्लोन फ़ंक्शन में अधिक विशिष्ट 'नया' का उपयोग कर सकता हूं एक ही परिणाम। – iforce2d

+2

डॉन, सी कोड एक सी ++ छद्म में: x मुझे लगता है कि आप जानते हैं कि आप स्मृति लीक कर रहे हैं? (हां यह अप्रासंगिक है, लेकिन मैं प्रस्तुत कोड में कुछ भी नहीं सोच सकता जो इस तरह के व्यवहार का उत्पादन करेगा)। और एक प्रासंगिक टिप्पणी के लिए: विधि के लिए उत्पन्न असेंबली क्या है? –

उत्तर

1

मैंने आपके कोड की कोशिश की और g ++ संस्करण 4.5.2 के साथ error: no matching function for call to ‘operator new(long unsigned int, void*&)‘ मिला ... मुझे यकीन नहीं है लेकिन आपके द्वारा उपयोग किया जाने वाला नया वाक्यविन्यास एक आंतरिक चीज़ होना चाहिए ...(नया (ज्ञापन) b2CircleShape)

हालांकि, जैसा कि मैथ्यूयू ने बताया, शायद यह नहीं है कि आप सी ++ में क्या करना चाहते हैं। एक क्लोन संभालने आप अपने वस्तुओं कॉपी कर सकते हैं (और आप अपने कोड में एक प्रतिलिपि करते हैं) बनाया जा रहा है बस है:

clone = new b2CircleShape(original); 
+3

'नया (mem) b2CircleShape'" एक आंतरिक चीज़ "नहीं है, यह [प्लेसमेंट' नया'] है (http://stackoverflow.com/questions/222557/what-uses-are-there-for-placement- new) । – DCoder

0

यह स्पष्ट है।

ए) यदि यह एक बार अपेक्षित काम करता है तो ठीक है। बी) तथ्य यह है कि त्रुटि फिर से होती है इसका मतलब केवल यह हो सकता है कि यह आपके जीसीसी में एक बग है। हां, यह सच है कि इन चीजों में बग हो सकते हैं। मैंने एमएसवीसी कंपाइलर को छोड़कर सभी कंपाइलरों में बग देखी है।

यदि आप जीसीसी या क्लैंग के लिए कोड प्राप्त करते हैं या जो भी हो और पता चलता है कि त्रुटि कहां होती है तो कुछ झंडे के कारण यह त्रुटि होगी। यदि यह एक बार काम करता है और फिर फिर से विफल रहता है तो कंपाइलर डेटा में झंडे या बिट बदल गए हैं और इसका मतलब है कि कंपाइलर में मेमोरी ओवररन या अन्य टाइपो।

क्षमा करें।

+1

मजेदार - मैंने केवल माइक्रोसॉफ्ट के 'सीएल' में बग देखा है;) –

+1

उसने कहा, मैंने इसे जीसीसी, बीसीसी और डेल्फी जितना उपयोग नहीं किया है, लेकिन हर जगह बग हैं और कभी-कभी कंपाइलर त्रुटियां भी सरल होती हैं! –

संबंधित मुद्दे