2010-09-03 14 views
6

पर एक -फनो-आरटीआई साझा लाइब्रेरी में अपवाद को पकड़ने के लिए पॉलिमॉर्फिक रूप से f-no-rtti के साथ साझा लाइब्रेरी का निर्माण कर रहा हूं। आंतरिक रूप से, यह लाइब्रेरी std:invalid_argument फेंकता है और std::exception पकड़ता है, लेकिन catch खंड कभी दर्ज नहीं किया जाता है।मैक ओएस एक्स

निम्नलिखित कोड समस्या reproduces (छ ++ 4.2, मैक ओएस एक्स 10.6):

// library.cpp: exports f(), compiled with -fno-rtti 
#include <stdexcept> 
#include <iostream> 
extern "C" { 
    void f() { 
     try { 
      throw std::invalid_argument("std::exception handler"); 
     } catch(std::exception& e) { 
      std::cout << e.what() << "\n"; 
     } catch(...) { 
      std::cout << "... handler\n"; 
     } 
    } 
} 

// main.cpp: the main executable, dynamically loads the library 
#include <dlfcn.h> 
typedef void(*fPtr)(); 

int main() { 
    void* handle = dlopen("./libexception_problem.dylib", RTLD_LAZY); 
    fPtr p_f = reinterpret_cast<fPtr>(dlsym(handle, "f")); 
    p_f(); 
} 

आउटपुट:

MacBook-Pro:teste pfranco$ # works fine with rtti 
MacBook-Pro:teste pfranco$ g++ -c library.cpp && g++ -shared -o libexception_problem.dylib library.o && g++ main.cpp -o main && ./main 
std::exception handler 
MacBook-Pro:teste pfranco$ # breaks with -fno-rtti 
MacBook-Pro:teste pfranco$ g++ -c -fno-rtti library.cpp && g++ -shared -o libexception_problem.dylib library.o && g++ -fno-rtti main.cpp -o main && ./main 
... handler 
MacBook-Pro:teste pfranco$ #-no_dead_strip_inits_and_terms doesn't change anything 
MacBook-Pro:teste pfranco$ g++ -c -no_dead_strip_inits_and_terms -fno-rtti library.cpp && g++ -no_dead_strip_inits_and_terms -shared -o libexception_problem.dylib library.o && g++ -fno-rtti -no_dead_strip_inits_and_terms main.cpp -o main && ./main 
... handler 
MacBook-Pro:teste pfranco$ # linking against the shared library works, but this isn't always an option 
MacBook-Pro:teste pfranco$ g++ -c -fno-rtti library.cpp && g++ -shared -o libexception_problem.dylib library.o && g++ -fno-rtti main.cpp -o main -L. -lexception_problem && ./main 
std::exception handler 

यह केवल तभी होता है जब साझा लाइब्रेरी में साझा किया गया कोड, और केवल तभी पकड़ा गया प्रकार वास्तविक वर्ग वास्तविक अपवाद - catch(std::invalid_argument&) ठीक काम करता है, std::logic_error& नहीं करता है।

दिलचस्प बात यह है कि यह लिनक्स पर नहीं होता है, यहां तक ​​कि सटीक वही आदेश चलाते समय भी।

सवाल:

  1. इस क्यों होता है? क्या यह एक बग, अपरिभाषित व्यवहार या डिजाइन द्वारा है?
  2. पुस्तकालय के खिलाफ जोड़ने से कम, मैं इसे कैसे काम कर सकता हूं?

बहुत बहुत धन्यवाद।

+0

यदि "अपरिभाषित व्यवहार" से आपका मतलब सी ++ मानक के अनुसार है, तो यह कार्यान्वयन-परिभाषित है जब आप एक कंपाइलर विकल्प का उपयोग करते हैं जो संकलक को गैर-अनुपालन मोड में रखता है।मुझे संदेह है कि आपको बहुत मदद मिलती है, लेकिन आप मानक के बिट्स को अक्षम नहीं कर सकते हैं और फिर मानक की आपकी मदद करने की उम्मीद कर सकते हैं ;-) –

उत्तर

3

ऐप्पल के जीसीसी पर यह एक बग बदल देता है। उन्होंने हाल ही में मेरी बग रिपोर्ट का जवाब दिया है कि यह तय नहीं किया जाएगा, हालांकि।

-2

जीसीसी (मेरे हाइलाइजिंग) के लिए जानकारी पृष्ठ से।

-fno-rtti सी ++ रनटाइम प्रकार पहचान द्वारा उपयोग के लिए आभासी कार्यों के साथ हर वर्ग के बारे में जानकारी की अक्षम पीढ़ी (dynamic_cast और typeid) की सुविधा है। यदि आप भाषा के उन हिस्सों का उपयोग नहीं करते हैं, तो आप इस ध्वज का उपयोग करके कुछ स्थान बचा सकते हैं। नोट कि अपवाद हैंडलिंग उसी जानकारी का उपयोग करता है, लेकिन यह आवश्यकतानुसार इसे उत्पन्न करेगा। dynamic_cast ऑपरेटर अभी भी उन स्थानों के लिए उपयोग किया जा सकता है जिन्हें रनटाइम प्रकार की जानकारी की आवश्यकता नहीं है, यानी void * या अस्पष्ट आधार वर्गों तक रहता है।

आरटीटीआई भाषा का मुख्य हिस्सा है। यदि संकलक आपको इसे अक्षम करने की अनुमति देता है, तो आप भाषा के नियमों के बाहर काम कर रहे हैं, इसलिए जरूरी नहीं है कि आप सबकुछ काम कर सकें।

+1

हाँ, मैं इसे पढ़ूंगा, लेकिन यह "इसे आवश्यकतानुसार उत्पन्न नहीं करेगा" प्रमुख हिस्सा? धन्यवाद। –

+0

@ पेड्रो डी एक्विनो: ईमानदार होने के लिए, मुझे नहीं पता। कठिनाई यह है कि अब आप एक भाषा संस्करण का उपयोग कर रहे हैं जिसे जीसीसी के वास्तव में व्यवहार से स्पष्ट रूप से परिभाषित किया गया है। मैं आरटीटीआई को अक्षम करने की कोशिश करने के खिलाफ सिफारिश करता हूं। –

+0

मैं एक ही चीज़ पोस्ट करने वाला था। यह मुझे बताता है कि अपवाद-प्रबंधन * सभी आवश्यक प्रकार की जानकारी उत्पन्न करने के लिए * माना जाता है, भले ही '-फनो-आरटीआईआई' निर्दिष्ट किया गया हो, जहां तक ​​जीसीसी का संबंध है। लेकिन मैंने ओएसएक्स या बीएसडी सिस्टम पर 'मैन' नहीं चलाया, इसलिए यह कुछ अलग कह सकता है। ऐसा हो सकता है कि उन्होंने जानबूझकर व्यवहार को बदल दिया है (और कहीं भी दस्तावेज किया गया है), हो सकता है कि उन्होंने चुपचाप इसे बदल दिया हो (और इसे कहीं भी दस्तावेज नहीं किया - बहुत शरारती), या यह उनके जीसीसी कांटा और/या में एक बग हो सकता है उनके सी ++ रनटाइम समर्थन। –