अंतिम अद्यतन:2026-10-12
C++ string ABI compatibility¶
प्रोजेक्ट प्रैक्टिस की समस्या: C++ String ABI compatibility समस्या से बचना¶
बहुत से लोग C++ string पसंद क्यों नहीं करते और खुद अपना चक्का (wheel) बनाते हैं? इनमें से एक समस्या है C++ string abi, क्या आपसे कभी यह हुआ है?
पहले conan और cross-platform लाइब्रेरी का उपयोग करते समय C++ string abi compatibility समस्या आई थी, यह सेक्शन ABI का बैकग्राउंड और कंपाइलर से जुड़ी बातें समझाएगा और बताएगा कि इस जाल से कैसे बचें, अगर आपसे यह हुआ है तो कमेंट करें~
1. ABI बदलाव का बैकग्राउंड¶
GCC 5.1 के बाद C++11 सपोर्ट और मज़बूत किया गया और कुछ नए फ़ीचर्स जोड़े गए। इस वर्ज़न में libstdc++ ने नई लाइब्रेरी ABI लाई, जिसमें std::string और std::list का इम्प्लीमेंटेशन अपडेट हुआ। ये बदलाव C++11 स्टैंडर्ड के अनुरूप हैं, जो Copy-On-Write string के उपयोग पर रोक लगाता है और लिंक्ड लिस्ट से उसका साइज़ ट्रैक करने की माँग करता है।
वास्तविक प्रोजेक्ट में Conan का उपयोग करते समय डेवलपर compiler.libcxx बदलकर उपयोग की जाने वाली ABI चुन सकता है:
- libstdc++: पुरानी ABI का उपयोग।
- libstdc++11: नई ABI का उपयोग।
उपयुक्त ABI चुनने से दूसरी dependency लाइब्रेरीज़ के साथ compatibility सुनिश्चित होती है, ख़ासकर अलग वर्ज़न के कंपाइलर या लाइब्रेरी के उपयोग के समय।
2. कंपाइलर की डिफ़ॉल्ट सेटिंग¶
GCC से कंपाइल करते समय, अगर स्पष्ट रूप से --with-default-libstdcxx-abi=gcc4-compatible निर्दिष्ट न किया जाए, तो GCC डिफ़ॉल्ट रूप से नई C++11 ABI उपयोग करता है। इसका मतलब है:
- अगर आपका कोड या dependency लाइब्रेरी पुरानी ABI से कंपाइल हुई है, तो link करने की कोशिश में आपको undefined symbol error मिल सकती है।
उदाहरण के लिए, निम्नलिखित कोड कंपाइल करते समय:
कमांड का उपयोग करते हुए:
सिंबल __Z3fooRKSs बनेगा, जो पुरानी ABI का फ़ॉर्मैट है।
हालाँकि, जब आप नई ABI उपयोग करने वाली दूसरी फ़ाइल कंपाइल और लिंक करते हैं, तो ऐसी error आ सकती है:
Undefined symbols for architecture x86_64:
"foo(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&)", referenced from:
_main in ccbWGoYh.o
ld: symbol(s) not found for architecture x86_64
collect2: error: ld returned 1 exit status
3. समाधान¶
कंपाइल सफल हो, इसके लिए दो समाधान हैं:
तरीका 1: ABI मैन्युअली निर्दिष्ट करें
सभी सोर्स फ़ाइलें कंपाइल करते समय पुरानी लाइब्रेरी के साथ compatibility के लिए मैन्युअली -D_GLIBCXX_USE_CXX11_ABI=0 जोड़ना सुनिश्चित करें, उदाहरण के लिए:
तरीका 2: सभी फ़ाइलें नई ABI से कंपाइल करें
अगर आप नई C++11 ABI उपयोग करने को तैयार हैं, तो लाइब्रेरी फ़ाइल कंपाइल करते समय -D_GLIBCXX_USE_CXX11_ABI=1 का उपयोग करें, इससे दोनों के सिंबल मैच हो जाएँगे:
इस स्थिति में link करते समय सिंबल मैच होंगे और undefined symbol की error नहीं आएगी।
4. सिंबल की तुलना¶
nm कमांड से अलग-अलग ABI के सिंबल देखकर दोनों का अंतर साफ़ देखा जा सकता है:
g++-14 -D_GLIBCXX_USE_CXX11_ABI=0 -c lib.cc
nm lib.o | grep foo
# 输出: 0000000000000000 T __Z3fooRKSs
g++-14 -D_GLIBCXX_USE_CXX11_ABI=1 -c lib.cc
nm lib.o | grep foo
# 输出: 0000000000000000 T __Z3fooRKNSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE
5. सारांश¶
ABI, C++ अपग्रेड और कंपाइल प्रक्रिया में मिलने वाला एक बहुत बड़ा जाल है, उम्मीद है इस लेख से ये बातें साफ़ हो गई होंगी।
संबंधित विषय¶
- C++ प्योर वर्चुअल फ़ंक्शन और एब्स्ट्रैक्ट क्लास | C++那些事
- C++ assert | C++那些事
- C++ bit-field | C++那些事
- C भाषा से C++ पॉलीमॉर्फ़िज़्म | C++那些事
- C++ const constant और qualifier | C++那些事
- C++ const परिवार | C++那些事
- C++ dereference ऑपरेटर * | C++那些事
- C++ इनिशियलाइज़ेशन और असाइनमेंट | C++那些事
- C++ multiple return values लिखने के तरीके | C++那些事
- C++ mutable कीवर्ड | C++那些事