2012-12-15 13 views
6

मुझे अपने कोड में एक लिंकर त्रुटि मिल रही है। मैंने इसे नीचे की जरूरी जरूरी चीजों पर ठोकर दिया है।"vtable" लिंकर त्रुटि ("= डिफ़ॉल्ट" के साथ एक आभासी विनाशक शामिल) - Clang 3.1 में संभावित बग?

इस कोड लिंकर त्रुटि "फू के लिए vtable", से संदर्भित देता है: फू :: फू()

class Foo { 
public: 
    Foo(); 
    virtual ~Foo() = default; 
}; 
Foo::Foo() { } 

लेकिन इस कोड कोई त्रुटि नहीं देता:

class Foo { 
public: 
    Foo(); 
    virtual ~Foo() { } 
}; 
Foo::Foo() { } 

क्यों? मैंने सोचा कि = default मूल रूप से उन खाली वर्ग ब्रैकेट के समान ही काम करना था।

अद्यतन: मैं एक्सकोड 4.5.2 का एक हिस्सा "ऐप्पल एलएलवीएम कंपाइलर 4.1" का उपयोग कर रहा हूं। क्या यह इस कंपाइलर में एक बग हो सकता है? यह संभवतः नवीनतम जीसीसी पर काम कर सकता है (हालांकि ऐप्पल अब शिपिंग नहीं कर रहा है)। कंपाइलर्स पर चर्चा के लिए नीचे टिप्पणियां देखें।

अपडेट 2: जैसा कि नीचे चर्चा की गई है, virtual inline ~Foo() = default; पर लाइन को बदलना इस त्रुटि से छुटकारा पाता है। क्या यह पर कोई बग नहीं है? ऐसा लगता है कि संकलक inline को स्पष्ट रूप से लिखने के बिना इस मामले में एक इनलाइन फ़ंक्शन को नहीं पहचानता है।

+0

'आभासी ~ Foo() noexcept = default;' आज़माएं। मुझे लगता है कि मुझे एक बार एक ही समस्या थी और 'डिफ़ॉल्ट' पर छोड़ दिया गया। इसके अलावा, मुझे लगता है कि इसके बारे में एक डीआर भी है। –

+0

@KerrekSB लिंकर त्रुटि अभी भी 'noexcept' के साथ है। –

+0

यह मेरे लिए जीसीसी 4.7.2 के साथ काम करता है। – Kocka

उत्तर

1

यह मेरे लिए g ++ 4.7.2 के साथ काम करता है। लेकिन मुझे वही समस्या है जैसे आप क्लैंग 3.1 के साथ हैं।

मेरे पास 3 फाइलें हैं।

Foo.h:

#ifndef FOO_H 
#define FOO_H 

class Foo { 
public: 
    Foo(); 
    virtual ~Foo() = default; 
}; 

#endif // FOO_H 

Foo.cpp:

#include "Foo.h" 

Foo::Foo() { } 

main.cpp:

#include <iostream> 
#include "Foo.h" 

using namespace std; 

int main() 
{ 
    Foo foo; 
    return 0; 
} 

लेकिन अगर यह इस तरह है, यह रूप में अच्छी तरह बजना साथ काम करता है :

Foo.cpp खाली है।

main.cpp

#include <iostream> 
#include "Foo.h" 

using namespace std; 

Foo::Foo() { } 

int main() 
{ 
    Foo foo; 
    return 0; 
} 

तो मुझे लगता है कि बजना objectfile पैदा करने के दौरान बग है।

2

इटेनियम एबीआई में, वी-टेबल (और अन्य आरटीटीआई सूचना) कक्षा में इनलाइन परिभाषित नहीं की गई पहली आभासी विधि की परिभाषा वाली अनुवाद इकाई के लिए उत्सर्जित है, या यदि केवल इनलाइन परिभाषित वर्चुअल विधियां हैं, कक्षा में शामिल प्रत्येक अनुवाद इकाई के लिए। यह अनावश्यक प्रतीकों को मर्ज करने के लिए लिंकर तक है।

यह संभव है कि = default निर्दिष्ट करके, बजना एहसास नहीं है कि आप परिभाषित कक्षा में virtual विधि इनलाइन है और प्रत्येक और हर टीयू कि आपकी फ़ाइल शामिल v-मेज और RTTI जानकारी परिभाषित करना चाहिए कि, और इसके बजाय परिभाषा के लिए कहीं और इंतजार कर रहा है।

क्या मैं कक्षा के बाहर परिभाषा डालने का सुझाव दे सकता हूं? =>Foo::~Foo() = default;

+0

यह वास्तव में 'Foo :: ~ Foo() = defa डालने के लिए काम करता था अल्ट; 'कार्यान्वयन फ़ाइल में (यानी। हेडर फ़ाइल नहीं है जहां कक्षा परिभाषा है)। हालांकि, दिलचस्प बात यह है कि यह कक्षा के भीतर लाइन में 'इनलाइन' जोड़ने के लिए भी काम करता है: 'आभासी इनलाइन ~ Foo() = डिफ़ॉल्ट;' क्या यह गारंटीकृत बग नहीं है? ऐसा लगता है कि यह इनलाइन को पहचान नहीं रहा है, भले ही यह इनलाइन है। –

+0

@ डेनिसरिची: यह निश्चित रूप से एक बग की तरह लगता है। मैं आश्चर्यचकित नहीं हूं क्योंकि '= डिफ़ॉल्ट' एक नया निर्माण है। सभी नई चीजों की तरह, इसमें बग को बाहर निकालने में समय लगता है। –

+0

मुझे अभी पता चला है कि लिंकर त्रुटि दूर हो जाती है अगर वहां 'उपूक्त' से प्राप्त उप-वर्ग मौजूद है (भले ही सबक्लास खाली हो)। क्या आपके पास कोई तकनीकी स्पष्टीकरण है कि यह कंपाइलर को और अधिक खुश क्यों करेगा? –

3

It appears to be a bug in clang which has been fixed already. आपने एक अच्छा समय पूछा, क्योंकि एक नई रिलीज जल्द ही आ रही है: release candidates are already available। कृपया उन्हें आज़माएं, आपका उदाहरण i386-linux बाइनरी रिलीज में काम करता है, और उन सभी में काम करना चाहिए।

+0

ओह, मीठा! मैं सिर्फ वास्तविक क्लैंग 3.2 के लिए एक्सकोड में दिखाई देने की प्रतीक्षा करूंगा। शायद महीनों लगेगा। तब तक मैं बस उस अतिरिक्त "इनलाइन" को रखूंगा। –

+1

अच्छा काम यह पता लगाना! मुझे पसंद है कि फिक्स कोड की दो पंक्तियां कैसे हैं;) –

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