2010-03-25 15 views
6

मुझे पता है कि __stdcall फ़ंक्शंस में इलिप्स नहीं हो सकते हैं, लेकिन मैं यह सुनिश्चित करना चाहता हूं कि कोई प्लेटफार्म नहीं है जो __cdecl या __stdcall के अलावा सम्मेलनों को कॉल करने के लिए stdarg.h फ़ंक्शंस का समर्थन करता है।सी ++ में, वैरिएडिक फ़ंक्शंस (पैरामीटर सूची के अंत में ... के साथ) आवश्यक रूप से __cdecl कॉलिंग सम्मेलन का पालन करें?

उत्तर

7

कॉलिंग सम्मेलन एक ऐसा होना चाहिए जहां कॉलर स्टैक से तर्क को साफ़ करता है (क्योंकि कैली को पता नहीं होता कि क्या पारित किया जाएगा)।

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

हालांकि मैं इसके बारे में कम निश्चित हूं, मैं लगभग आईए 64 (इटेनियम) पर वही अपेक्षा करता हूं - इसमें एक विशाल रजिस्टर सेट भी है (मेमोरी परोसने पर कुछ सौ)। अगर मुझे गलत नहीं लगता है, तो यह रजिस्टरों का उपयोग करने के तरीके के बारे में थोड़ा अधिक अनुमोदित है, लेकिन मुझे उम्मीद है कि इसे कम से कम बहुत समय तक इस्तेमाल किया जाए।

यह आपके लिए क्यों मायने रखता है? Stdarg.h और उसके मैक्रोज़ का उपयोग करने का बिंदु अपने कोड से सम्मेलन को कॉल करने में मतभेदों को छिपाना है, इसलिए यह पोर्टेबल परिवर्तनीय तर्कों के साथ काम कर सकता है।

टिप्पणियों के आधार पर संपादित करें: ठीक है, अब मैं समझता हूं कि आप क्या कर रहे हैं (कम से कम उत्तर में सुधार करने के लिए पर्याप्त)। यह देखते हुए कि आप पहले से ही (स्पष्ट रूप से) डिफ़ॉल्ट एबीआई में बदलावों को संभालने के लिए कोड रखते हैं, चीजें सरल होती हैं। यह केवल सवाल पूछता है कि क्या विविध कार्य हमेशा "डिफ़ॉल्ट एबीआई" का उपयोग करते हैं, जो प्लेटफ़ॉर्म के लिए जो कुछ भी होता है। एकमात्र विकल्प के रूप में "stdcall" और "default" के साथ, मुझे लगता है कि इसका उत्तर हाँ है। उदाहरण के लिए, विंडोज़ पर, wsprintf और wprintf अंगूठे के नियम को तोड़ते हैं, और stdcall की बजाय cdecl कॉलिंग सम्मेलन का उपयोग करते हैं।

+1

एसपीएआरसी के बारे में आपकी टिप्पणी कई आरआईएससी आर्किटेक्चर नहीं होने पर लागू होती है। चूंकि रजिस्ट्रार इतने भरपूर हैं, इसलिए कंपाइलर केवल तर्कों को पारित करने के लिए उपयोग करता है। उल्लेख नहीं है, वे काफी हद तक स्मृति से तेज हैं, esp। चूंकि आप पहले से ही रजिस्टरों में डेटा पास कर रहे हैं (हालांकि मुझे लगता है कि उन्हें उन्हें बहाल करने के लिए उन्हें स्टैक पर धक्का देना होगा, लेकिन बाद में उन्हें चाहिए, लेकिन ...)। वैसे भी, मुझे पता है कि यह एमआईपीएस पर काम करता है और मुझे पूरा यकीन है कि पीपीसी एक ही तरीके से काम करता है। –

+2

* "यह आपके लिए क्यों मायने रखता है?" * बेन मोज़िला के लिए जेएस-सीटीपीएस पर काम कर रहा है। आप https://bugzilla.mozilla.org/show_bug.cgi?id=554790 ("पागल विचार" के लिए खोज) में सटीक संदर्भ देख सकते हैं और आप https: //developer.mozilla पर जेएस-सीटीपीएस को समझाते हुए कुछ दस्तावेज़ कर सकते हैं। संगठन/एन/जावास्क्रिप्ट_code_modules/ctypes.jsm –

+0

कहने की जरूरत नहीं है, जेएस-सीटीपीएस केवल एप्लिकेशन कोड और एड-ऑन के लिए उपलब्ध है, न कि वेब पेज। –

0

आप 'MSVC द्वारा समर्थित प्लेटफार्मों मतलब है "या एक सामान्य नियम के रूप में? यहाँ तक कि यदि आप अपने आप को MSVC द्वारा समर्थित प्लेटफार्मों तक सीमित है, तो आप अभी भी IA64 और AMD64 तरह की स्थितियों है जहां केवल" एक "सम्मेलन बुला, और सम्मेलन बुला __stdcall कहा जाता है कि है, लेकिन यह निश्चित रूप से एक ही __stdcall आप 86 पर नहीं मिलता है।

0

AFAIK, सम्मेलनों बुलाने की विविधता 86 पर DOS/Windows के लिए अद्वितीय है। अधिकांश अन्य प्लेटफार्मों compilers ओएस के साथ आया था और मानकीकरण सम्मेलन

2

कॉलिन का विश्लेषण करने का सबसे निश्चित तरीका यह है कि आप इसे निर्धारित कर सकते हैं जी सम्मेलन

  • कॉल प्राप्त करने वाला पैरामीटर से एक निश्चित ढेर के ऊपर से ऑफसेट चर तर्क सूची का हिस्सा नहीं हैं का उपयोग करने में सक्षम होना चाहिए: variadic कार्यों काम करने के लिए, तो आपके कॉलिंग सम्मेलन विशेषताओं की एक जोड़ी की जरूरत है । इसके लिए यह आवश्यक है कि संकलक पैरामीटर को दाएं से बाएं स्टैक पर धक्का दें। (इसमें printf, प्रारूप विनिर्देश के पहले पैरामीटर जैसी चीजें शामिल हैं। साथ ही, वेरिएबल तर्क सूची का पता भी एक ज्ञात स्थान से लिया जाना चाहिए।)
  • कॉलर को पैरामीटर को हटाने के लिए जिम्मेदार होना चाहिए फ़ंक्शन वापस लौटने के बाद स्टैक करें, क्योंकि केवल कंपाइलर, कॉलर के लिए कोड उत्पन्न करते समय, जानता है कि पहले स्थान पर कितने पैरामीटर को धक्का दिया गया था। विविधता फ़ंक्शन में यह जानकारी नहीं है।

stdcall काम नहीं करेगा क्योंकि कैली स्टैक से पैरामीटर को पॉप करने के लिए ज़िम्मेदार है। पुराने 16-बिट विंडोज़ दिनों में, pascal काम नहीं करेगा क्योंकि यह बाएं से दाएं स्टैक पर पैरामीटर को धक्का देता है।

बेशक, जैसा कि अन्य उत्तरों ने संकेत दिया है, कई प्लेटफ़ॉर्म आपको कॉलिंग सम्मेलन के मामले में कोई विकल्प नहीं देते हैं, जिससे यह प्रश्न उन लोगों के लिए अप्रासंगिक बना देता है।

1

एक x86 सिस्टम पर निम्नलिखित समारोह पर विचार करें:

शून्य __stdcall कुछ (चार *, ...);

फ़ंक्शन खुद को __stdcall के रूप में घोषित करता है, जो एक कैली-क्लीन सम्मेलन है। लेकिन एक वैरिएड फ़ंक्शन कैली-क्लीन नहीं हो सकता है क्योंकि कैली को पता नहीं है कि कितने पैरामीटर पारित किए गए थे, इसलिए यह नहीं पता कि इसे कितने साफ करना चाहिए।

माइक्रोसॉफ्ट विजुअल स्टूडियो सी/सी ++ कंपाइलर कॉलिंग कन्वेंशन को चुपचाप __cdecl में परिवर्तित करके इस संघर्ष को हल करता है, जो कि इस पैरामीटर को छिपाने वाले कार्यों के लिए एकमात्र समर्थित वैरडिक कॉलिंग सम्मेलन है।

चेतावनी या त्रुटि उत्पन्न करने के बजाय यह रूपांतरण चुपचाप क्यों होता है?

मेरा अनुमान है कि यह कंपाइलर विकल्प/जीआर (डिफ़ॉल्ट कॉलिंग कन्वेंशन को __fastcall पर सेट करें) और/Gz (डिफ़ॉल्ट कॉलिंग कन्वेंशन को __stdcall पर सेट करें) कम परेशान करना है।

__cdecl के लिए वैरैडिक फ़ंक्शंस का स्वचालित रूपांतरण का अर्थ है कि आप अपने कंपाइलर विकल्पों में/gr या/gz कमांड लाइन स्विच जोड़ सकते हैं, और सबकुछ अभी भी संकलित और चलाएगा (केवल नए कॉलिंग सम्मेलन के साथ)।

इस को देखने का एक और तरीका है variadic __stdcall परिवर्तित __cdecl को बल्कि बस कह कर के रूप में संकलक की सोच से नहीं है "variadic कार्यों के लिए, __stdcall कॉलर-साफ है।"

click here

संबंधित मुद्दे

 संबंधित मुद्दे