__Gxx_personality_v0 के लिए क्या है?


103

यह एक ओएस विकास साइट से एक दूसरे हाथ का सवाल है, लेकिन यह मुझे उत्सुक बना दिया क्योंकि मैं कहीं भी एक अच्छी व्याख्या नहीं पा सका।

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

out/kernel.o:(.eh_frame+0x11): undefined reference to `__gxx_personality_v0'

यह स्पष्ट रूप से है क्योंकि यह प्रतीक libstdc ++ में परिभाषित किया गया है, जो एक मुक्त वातावरण में गायब है। समस्या को ठीक करने के लिए बस इस प्रतीक को परिभाषित करने की आवश्यकता है:

void *__gxx_personality_v0;

जो अच्छा है, लेकिन मुझे ऐसी चीजें पसंद नहीं हैं जो सिर्फ जादुई रूप से काम करती हैं ... तो सवाल यह है कि इस प्रतीक का उद्देश्य क्या है?

जवाबों:


93

इसका उपयोग स्टैक अनवाइडिंग टेबल में किया जाता है, जिसे आप मेरे प्रश्न के उत्तर के असेंबली आउटपुट में उदाहरण के लिए देख सकते हैं । जैसा कि उस उत्तर पर उल्लेख किया गया है, इसका उपयोग इटेनियम सी ++ एबीआई द्वारा परिभाषित किया गया है , जहां इसे व्यक्तित्व दिनचर्या कहा जाता है ।

इसका कारण यह है कि इसे एक वैश्विक NULL void पॉइंटर के रूप में परिभाषित करके "काम करता है" शायद इसलिए कि कोई अपवाद नहीं फेंक रहा है। जब कोई चीज एक अपवाद को फेंकने की कोशिश करती है, तो आप इसे दुर्व्यवहार देखेंगे।

बेशक, अगर कुछ भी अपवादों का उपयोग नहीं कर रहा है, तो आप उन्हें -fno-exceptions(और अगर आरटीटीआई का उपयोग नहीं कर रहे हैं, तो आप भी जोड़ सकते हैं -fno-rtti)। यदि आप उनका उपयोग कर रहे हैं, तो आपको g++इसके बजाय लिंक के साथ (जैसा कि पहले से ही उल्लेख किया गया है) लिंक करना gccहोगा, जो -lstdc++आपके लिए जोड़ देगा ।


2
टिप के बारे में धन्यवाद -fno-exceptions। मैंने CPPFLAGS += -fno-exceptionsअपने मेकफाइल में जोड़ा , और उस त्रुटि को हल किया।
एलन किन्नमन

12

यह अपवाद से निपटने का हिस्सा है। Gcc EH तंत्र विभिन्न EH मॉडल को मिलाने की अनुमति देता है, और यह निर्धारित करने के लिए कि एक अपवाद मैच, क्या अंतिम रूप देना है, आदि के लिए एक व्यक्तित्व दिनचर्या का उपयोग किया जाता है। यह विशिष्ट व्यक्तित्व दिनचर्या C ++ अपवाद से निपटने के लिए है (जैसा कि, gcj / Java में विरोध किया गया है) उपवाद सम्भालना)।


11

अपवाद हैंडलिंग मुक्त खड़े कार्यान्वयन में शामिल है।

इसका कारण यह है कि आप संभवतः gccअपने कोड को संकलित करने के लिए उपयोग करते हैं। यदि आप विकल्प के साथ संकलित करते हैं, -###तो आप देखेंगे कि यह लिंकर-विकल्प याद कर रहा है -lstdc++जब यह लिंकर प्रक्रिया को आमंत्रित करता है। संकलित करने g++में वह पुस्तकालय शामिल होगा, और इस प्रकार उसमें अंकित प्रतीक।


मैंने हमेशा सोचा था कि जी ++ के साथ संकलन केवल तब आवश्यक था जब आप विशेष रूप से संकलक को बताना चाहते थे कि कोड सी ++ था (उदाहरण के लिए- विस्तार विस्तार)। अब ऐसा लगता है कि g ++ के साथ C ++ कोड का संकलन आने वाले पुस्तकालयों को शामिल करता है। इसके अलावा कुछ पुस्तकालयों लापता से, वहाँ मेरी संकलन के कुछ अन्य "दुष्प्रभाव" कर रहे हैं file.cppके साथ gccके बजाय g++?
लेज़र

1
@ekkay जहाँ तक मुझे पता है, दोनों का जुड़ाव libstdc++केवल एक अंतर है।
जोहान्स स्काउब -

6

libstd++कोड बेस के एक त्वरित grep ने निम्नलिखित दो उपयोगों का खुलासा किया __gx_personality_v0:

Libsupc ++ / खोलना-cxx.h में

// GNU C++ personality routine, Version 0.                                      
extern "C" _Unwind_Reason_Code __gxx_personality_v0
     (int, _Unwind_Action, _Unwind_Exception_Class,
      struct _Unwind_Exception *, struct _Unwind_Context *);

Libsupc ++ / eh_personality.cc में

#define PERSONALITY_FUNCTION    __gxx_personality_v0
extern "C" _Unwind_Reason_Code
PERSONALITY_FUNCTION (int version,
                      _Unwind_Action actions,
                      _Unwind_Exception_Class exception_class,
                      struct _Unwind_Exception *ue_header,
                      struct _Unwind_Context *context)
{
  // ... code to handle exceptions and stuff ...
}

(नोट: यह वास्तव में उससे थोड़ा अधिक जटिल है; कुछ सशर्त संकलन है जो कुछ विवरण बदल सकते हैं)।

इसलिए, जब तक आपका कोड वास्तव में अपवाद से निपटने का उपयोग नहीं कर रहा है, तब तक प्रतीक को परिभाषित करना void*कुछ भी प्रभावित नहीं करेगा, लेकिन जैसे ही यह होता है, आप दुर्घटनाग्रस्त होने जा रहे हैं - __gxx_personality_v0एक फ़ंक्शन है, कुछ वैश्विक वस्तु नहीं है, इसलिए कोशिश कर रहा है कॉल करने के लिए फ़ंक्शन 0 को संबोधित करने और एक segfault का कारण बनने के लिए कूदने जा रहा है।


जरूरी नहीं कि 0 पर कूदें; वैश्विक असंवैधानिक है इसलिए यह वास्तव में कोई भी मूल्य हो सकता है।
strager

6
स्ट्रिंगर, ग्लोबल्स को शून्य आरंभीकृत किया जाता है यदि प्रोग्रामर उन्हें इनिशियलाइज़ नहीं करता है
जोहान्स स्काउब - लीव

@ नोट: यह केवल तभी सही है जब कर्नेल bss अनुभाग को शून्य करता है :-P। लेकिन हाँ, उन्हें पवित्रता के लिए 0 आरम्भिक होना चाहिए।
इवान टेरान

9
@ इवान टेरान: नहीं, एक अनुरूप सी कार्यान्वयन हमेशा ग्लोबल्स को 0. को प्रारंभ करेगा। C99 मानक के Ter5.1.2 और paragraph6.7.8 पैरा 10 देखें।
एडम रोसेनफील्ड

6

मुझे एक बार यह त्रुटि हुई थी और मुझे इसका पता चला:

मैं एक gcc संकलक का उपयोग कर रहा था और मेरी फ़ाइल को तब बुलाया CLIENT.Cगया था जब मैं C प्रोग्राम नहीं कर रहा था और C ++ प्रोग्राम नहीं कर रहा था।

gcc .CC ++ प्रोग्राम के रूप में एक्सटेंशन और C प्रोग्राम के रूप में एक्सटेंशन को पहचानता है .c(छोटे c और बड़े C से सावधान रहें)।

इसलिए मैंने अपने फ़ाइल CLIENT.cप्रोग्राम का नाम बदल दिया और यह काम कर गया।


2

उपरोक्त उत्तर सही हैं: इसका उपयोग अपवाद हैंडलिंग में किया जाता है। मैनुअल जीसीसी संस्करण 6 के लिए अधिक जानकारी (अब भी मौजूद है जो संस्करण 7 के मैनुअल में) है। बाहरी फ़ंक्शन को लिंक करते समय त्रुटि उत्पन्न हो सकती है - जो जीसीसी के लिए अज्ञात है - जावा अपवादों को फेंकता है।

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.