c++ - इनलाइन स्थिर डेटा के कारण एक अनुभाग प्रकार संघर्ष होता है




gcc linker (3)

कस्टम अनुभागों के साथ गड़बड़ एक गंदे विषय का एक छोटा कारण है क्योंकि जीआईसी इनैट मूल्य के आधार पर डेटा या बीएसएस पर निर्णय लेता है और उस स्तर पर आपको इसके साथ गड़बड़ी की उम्मीद नहीं करता है।

मैं उपयोगकर्ता डेटा के लिए सुझाव देता हूं कि इसका उपयोग आम तौर पर डेटा का उपयोग करने के लिए करना है - इसे किसी डेटा फ़ाइल में रखें। यदि आप लाइब्रेरी का उपयोग करने पर जोर देते हैं, तो आप कम से कम इसे अपनी लाइब्रेरी का उपयोग कर सकते हैं और फिर डेटा सामान्य स्थानों में हो सकता है।

एक छोटे उपयोगकर्ता उदारीकरण, आसानी से पार्सिंग के लिए डेटा अनुभाग में सभी उपयोगकर्ता डेटा -fno-zero-initialized-in-bss लिए -fno-zero-initialized-in-bss साथ बनाया जा सकता है। लेकिन अपने बायनेरिज़ पर ऐसा न करें।

मैं एक कस्टम अनुभाग में कुछ उपयोगकर्ता परिभाषित डेटा को एक ही समय में एप्लिकेशन और एक ऑफ़लाइन विश्लेषक द्वारा पढ़ना चाहता हूं। निम्नलिखित नमूने मान लें:

const int* get_data()
{
  __attribute__((section(".custom")))
  static const int data = 123;

  return & data;
}

inline const int* inline_get_data()
{
  __attribute__((section(".custom")))
  static const int inline_data = 123;

  return & inline_data;
}

int main()
{
  (void) get_data();
  (void) inline_get_data();
  return 0;
}

data का मूल्य और inline_data अनुभाग में दिखाई देगा। .custom क्लैग इस उदाहरण को संकलित करता है और सही परिणाम उत्पन्न करता है, जैसे कि एमएसवीसी करता है, जब __ डेटा का योगदान दिया जाता है, तो इसी प्रगामा द्वारा बदल दिया जाता है।

दुर्भाग्य से, जीसीसी 5.2 निम्नलिखित त्रुटि देता है:

error: inline_data causes a section type conflict with data

समस्या यह है कि दो चर में अलग-अलग लिंकेज हैं ( data एक से चिह्नित किए गए अनुभाग में है, inline_data के अनुभाग को aG साथ चिह्नित किया गया है)। जीसीसी 4.9 उसी तरह विफल हो जाता है यदि दूसरे फ़ंक्शन को इनलाइन के रूप में चिह्नित नहीं किया गया है, लेकिन एक टेम्पलेट (जीसीसी 5.2 संकलित है)।

जीसीसी 5.2 भी ठीक से संकलित करता है यदि एक खंड नाम अस्थायी रूप से बदल दिया गया है और मैन्युअल रूप से जनित विधानसभा में तय किया गया है।

क्या इस मुद्दे के लिए कोई ज्ञात समाधान है? फ़ंक्शन के हस्ताक्षर पर मेरे पास कोई नियंत्रण नहीं है, *data चर मेरे द्वारा दिए गए मैक्रो द्वारा उत्पादित किए जाते हैं, और वे कहीं भी दिखाई दे सकते हैं।


जीसीसी दस्तावेज़ीकरण (उदाहरण के लिए 5.3 ) कहते हैं:

वैश्विक चर के साथ अनुभाग विशेषता का उपयोग करें और स्थानीय चर नहीं [...]

इस प्रकार, आपको कार्य से उन चर को निकालने की आवश्यकता है:

__attribute__((section(".custom"))) static const int data = 123;
__attribute__((section(".custom"))) static const int inline_data = 123;

const int* get_data()
{
  return &data;
}

inline const int* inline_get_data()
{
  return &inline_data;
}

int main()
{
  (void)get_data();
  (void)inline_get_data();
} 

यह सिर्फ जीसीसी -5 5.2 और क्लैग-3.5.1 के साथ ठीक है


अंत में मुझे एक संतोषजनक समाधान मिला। यह वास्तव में पहले से ही ज्ञात तकनीकों का संयोजन है रनटाइम एक सामान्य स्थिर वैरिएबल का उपयोग करता है, जिसका पता इनलाइन असेंबल द्वारा कस्टम अनुभाग में रखा जाता है। एएसएम के बिना, अलग-अलग प्लेटफार्मों (क्लैग, एमएसवीसी), __attribute__ या #pragma __attribute__ पर उसी परिणाम के साथ इस्तेमाल किया जा सकता है। यह समाधान आसानी से एक सामान्य, मंच अज्ञेयवादी मैक्रो में लपेटा जा सकता है।

const int* get_data()
{
  static const int data = 123;
  __asm__(
    ".pushsection .custom, \"?\", @progbits" "\n"
    ".quad %c0" "\n"
    ".popsection" "\n"
    : : "i"(&data)
  );

  return & data;
}

inline const int* inline_get_data()
{
  static const int inline_data = 123;
  __asm__(
    ".pushsection .custom, \"?\", @progbits" "\n"
    ".quad %c0" "\n"
    ".popsection" "\n"
    : : "i"(&inline_data)
  );

  return & inline_data;
}

int main()
{
  (void) get_data();
  (void) inline_get_data();
  return 0;
}