2011-11-30 12 views
6

यह प्रश्न this one से संबंधित है और इसके उत्तर से संबंधित है।साझा लाइब्रेरी में पीआईसी और गैर-पीआईसी वस्तुओं को मिलाकर

मैंने अभी एक ऐसे निर्माण में कुछ कुरूपता की खोज की है जिस पर मैं काम कर रहा हूं। स्थिति कुछ हद तक निम्न दिखती है (जीएमके प्रारूप में लिखी गई); ध्यान दें, यह विशेष रूप से स्पार्क और 86 हार्डवेयर पर एक 32-बिट स्मृति मॉडल पर लागू होता है:

OBJ_SET1 := some objects 
OBJ_SET2 := some objects 

# note: OBJ_SET2 doesn't get this flag 
${OBJ_SET1} : CCFLAGS += -PIC 

${OBJ_SET1} ${OBJ_SET2} : %.o : %.cc 
    ${CCC} ${CCFLAGS} -m32 -o ${@} -c ${<} 

obj1.o  : ${OBJ_SET1} 
obj2.o  : ${OBJ_SET2} 
sharedlib.so : obj1.o obj2.o 
obj1.o obj2.o sharedlib.so : 
    ${LINK} ${LDFLAGS} -m32 -PIC -o ${@} ${^} 

जाहिर है यह एक साझा वस्तु में साथ और पीआईसी के बिना संकलित वस्तुओं मिश्रण (इस प्रयोग में वर्षों के लिए किया गया है) काम कर सकते हैं । मुझे यह जानने के लिए पीआईसी के बारे में पर्याप्त जानकारी नहीं है कि यह एक अच्छा विचार/स्मार्ट है, और मेरा अनुमान इस मामले में है, इसकी आवश्यकता नहीं है, बल्कि यह हो रहा है क्योंकि किसी को सामना करने के दौरान सही तरीके से पता लगाने के लिए पर्याप्त परवाह नहीं है निर्माण के लिए नई चीजों पर।

मेरा प्रश्न है:

  1. इस सुरक्षित
  2. यह एक अच्छा विचार
  3. क्या संभावित समस्याओं परिणामस्वरूप
  4. के रूप में हो सकता है मैं पीआईसी के लिए सब कुछ स्विच करते हैं, वहाँ किसी भी गैर हैं -बेशक गेटचास जिन्हें मैं देखना चाहता हूं।

उत्तर

4

भूल गए मैंने यह प्रश्न भी लिखा था।

कुछ स्पष्टीकरण पहले के आदेश में हैं:

  • गैर पीआईसी कोड [? सबसे] आधुनिक OS के स्मृति में किसी भी स्थिति में ओएस द्वारा लोड किया जा सकता है। सब कुछ लोड होने के बाद, यह एक चरण के माध्यम से जाता है जो पाठ खंड को ठीक करता है (जहां निष्पादन योग्य सामान समाप्त होता है) ताकि यह वैश्विक चर को सही ढंग से संबोधित कर सके; इसे खींचने के लिए, पाठ खंड लिखने योग्य होना चाहिए।
  • पीआईसी निष्पादन योग्य डेटा ओएस द्वारा एक बार लोड किया जा सकता है और एकाधिक उपयोगकर्ताओं/प्रक्रियाओं में साझा किया जा सकता है। ओएस के लिए ऐसा करने के लिए, हालांकि, टेक्स्ट सेगमेंट केवल पढ़ने के लिए होना चाहिए - जिसका मतलब है कि कोई फिक्स-अप नहीं है। कोड को ग्लोबल ऑफसेट टेबल (जीओटी) का उपयोग करने के लिए संकलित किया गया है ताकि यह फिक्स-अप की आवश्यकता को कम करने के लिए जीओटी के सापेक्ष ग्लोबल्स को संबोधित कर सके।
  • यदि कोई साझा वस्तु पीआईसी के बिना बनाई गई है, हालांकि इसे दृढ़ता से प्रोत्साहित किया जाता है कि ऐसा नहीं लगता है कि यह कड़ाई से जरूरी है; यदि ओएस को टेक्स्ट सेगमेंट को ठीक करना होगा तो उसे इसे स्मृति में लोड करने के लिए मजबूर होना पड़ता है जिसे रीड-राइट चिह्नित किया जाता है ... जो प्रक्रियाओं/उपयोगकर्ताओं में साझा करना रोकता है।
  • यदि एक निष्पादन योग्य बाइनरी/पीआईसी के साथ बनाया गया है, तो मुझे नहीं पता कि हुड के नीचे क्या गलत है लेकिन मैंने देखा है कि कुछ टूल्स अस्थिर हो गए हैं (रहस्यमय क्रैश & जैसा)।

जवाब:

  • मिश्रण पीआईसी/गैर पीआईसी, या का उपयोग कर निष्पादनयोग्य में पीआईसी की भविष्यवाणी और अस्थायित्व को ट्रैक करने के लिए कठिन हो सकता है। मेरे पास तकनीकी स्पष्टीकरण क्यों नहीं है।
    • ... segfaults, बस त्रुटियों, ढेर ढेर, और शायद इसके अलावा।
  • साझा वस्तुओं में गैर-पीआईसी शायद किसी भी गंभीर समस्या का कारण नहीं बन रहा है, हालांकि इसके परिणामस्वरूप अधिक रैम का उपयोग किया जा सकता है यदि लाइब्रेरी प्रक्रियाओं और/या उपयोगकर्ताओं में कई बार उपयोग की जाती है।

अद्यतन (4/17)

के बाद से कुछ दुर्घटनाओं मैं पहले देखा था की के कारण की खोज की मैंने। इसे समझने के लिए:

/*header.h*/ 
#include <map> 
typedef std::map<std::string,std::string> StringMap; 
StringMap asdf; 

/*file1.cc*/ 
#include "header.h" 

/*file2.cc*/ 
#include "header.h" 

int main(int argc, char** argv) { 
    for(int ii = 0; ii < argc; ++ii) { 
    asdf[argv[ii]] = argv[ii]; 
    } 

    return 0; 
} 

... तो: विशिष्ट उदाहरण दुर्घटनाग्रस्त खत्म नहीं हो सकता है

$ g++ file1.cc -shared -PIC -o libblah1.so 
$ g++ file1.cc -shared -PIC -o libblah2.so 
$ g++ file1.cc -shared -PIC -o libblah3.so 
$ g++ file1.cc -shared -PIC -o libblah4.so 
$ g++ file1.cc -shared -PIC -o libblah5.so 

$ g++ -zmuldefs file2.cc -Wl,-{L,R}$(pwd) -lblah{1..5} -o fdsa 
#  ^^^^^^^^^ 
#  This is the evil that made it possible 
$ args=(this is the song that never ends); 
$ eval ./fdsa $(for i in {1..100}; do echo -n ${args[*]}; done) 

यही कारण है, लेकिन यह मूल रूप से स्थिति है कि उस समूह के कोड में अस्तित्व में था है। यदि यह क्रैश करता है तो यह संभवतः विनाशक में होगा, आमतौर पर एक डबल-फ्री त्रुटि।

कई सालों पहले उन्होंने -zmuldefs को अपने निर्माण के लिए गुणा परिभाषित प्रतीक त्रुटियों से छुटकारा पाने के लिए जोड़ा। संकलक वैश्विक वस्तुओं पर कन्स्ट्रक्टर/विनाशकों को चलाने के लिए कोड उत्सर्जित करता है। -zmuldefs उन्हें मेमोरी में एक ही स्थान पर रहने के लिए मजबूर करता है लेकिन यह अभी भी एक्सई के लिए रचनाकारों/विनाशकों को चलाता है और प्रत्येक पुस्तकालय जिसमें अपमानजनक हेडर शामिल होता है - इसलिए डबल-फ्री।