2009-08-20 14 views
48

मैं इन दिनों __stdcall पर आया हूं।
और मेरी राय में, एमएसडीएन वास्तव में इसका स्पष्ट अर्थ नहीं बताता है कि इसका वास्तव में क्या अर्थ है,
इसका उपयोग कब और क्यों किया जाना चाहिए।__stdcall का अर्थ और उपयोग क्या है?

अगर कोई स्पष्टीकरण प्रदान करेगा, तो अधिमानतः एक उदाहरण या दो के साथ मैं सराहना करता हूं।

धन्यवाद

उत्तर

45

सी/सी ++ में सभी फ़ंक्शन एक विशेष कॉलिंग सम्मेलन है। कॉलिंग कन्वेंशन का मुद्दा यह निर्धारित करना है कि कॉलर और कैली के बीच डेटा कैसे पारित किया जाता है और कॉल स्टैक को साफ करने जैसे संचालन के लिए कौन जिम्मेदार है।

खिड़कियों पर सबसे लोकप्रिय बुला सम्मेलनों

  • stdcall
  • cdecl
  • clrcall
  • fastcall
  • thiscall

हैं अनिवार्य रूप से बताता है कि समारोह घोषणा करने के लिए इस विनिर्देशक जोड़ना आप संकलक है कि आप इस विशेष समारोह को यह विशेष कॉलिंग सम्मेलन रखना चाहते हैं।

बुला सम्मेलनों यहाँ

प्रलेखित रेमंड चेन भी विभिन्न बुला सम्मेलनों (5 भागों) यहाँ शुरू करने के इतिहास पर एक लंबी श्रृंखला किया था।

1

एक कॉलिंग परंपरा है कि WinAPI कार्यों ठीक से कहा जा करने की आवश्यकता है यही कारण है कि। एक कॉलिंग सम्मेलन नियमों का एक सेट है कि पैरामीटर को फ़ंक्शन में कैसे पारित किया जाता है और फ़ंक्शन से वापसी मूल्य कैसे पारित किया जाता है।

यदि कॉलर और कॉल किया गया कोड अलग-अलग सम्मेलनों का उपयोग करता है तो आप अपरिभाषित व्यवहार (जैसे such a strange-looking crash) में चलाते हैं।

सी ++ compilers डिफ़ॉल्ट रूप से __stdcall का उपयोग नहीं करते - वे अन्य सम्मेलनों का उपयोग करें। तो सी ++ से WinAPI फ़ंक्शंस को कॉल करने के लिए आपको यह निर्दिष्ट करने की आवश्यकता है कि वे __stdcall का उपयोग करते हैं - यह आमतौर पर विंडोज़ एसडीके हेडर फाइलों में किया जाता है और फ़ंक्शन पॉइंटर्स घोषित करते समय भी आप इसे करते हैं।

3

यह एक समारोह के लिए एक कॉलिंग सम्मेलन निर्दिष्ट करता है। एक कॉलिंग सम्मेलन नियमों का एक सेट है कि फ़ंक्शन पर पैरामीटर कैसे पारित किए जाते हैं: किस क्रम में, प्रति पता या प्रति प्रति, जो पैरामीटर (कॉलर या कैली) आदि को साफ करना है

5

दुर्भाग्य से, वहाँ जब यह उपयोग करने के लिए और जब नहीं करने के लिए कोई आसान जवाब है।

__stdcall मतलब है कि एक समारोह के लिए तर्क पिछले करने के लिए पहले से ढेर पर धकेल दिया जाता है।यह __cdecl के विपरीत है, जिसका अर्थ है कि तर्कों को अंतिम से पहले तक धक्का दिया जाता है, और __fastcall, जो रजिस्टरों में पहले चार (मुझे लगता है) तर्क देता है, और बाकी स्टैक पर जाते हैं।

आपको सिर्फ यह जानने की जरूरत है कि कैली की क्या अपेक्षा है, या यदि आप लाइब्रेरी लिख रहे हैं, तो आपके कॉलर्स की क्या अपेक्षा है, और सुनिश्चित करें कि आप अपने चुने हुए सम्मेलन को दस्तावेज करते हैं।

+2

'__stdcall' और' __cdecl' केवल वापसी (और सजावट) के बाद सफाई के लिए ज़िम्मेदारी में भिन्नता है। तर्क दोनों गुजरने के लिए समान है (दाएं से बाएं)। आप जो वर्णन कर रहे हैं वह पास्कल कॉलिंग सम्मेलन है। – a3f

6

__stdcall एक कॉलिंग सम्मेलन है: यह निर्धारित करने का एक तरीका है कि किसी फ़ंक्शन (स्टैक या रजिस्टरों पर) पैरामीटर कैसे पास किए जाते हैं और फ़ंक्शन रिटर्न (कॉलर या कैली) के बाद सफाई के लिए कौन जिम्मेदार होता है।

रेमंड चेन ने blog about the major x86 calling conventions लिखा, और वहां एक अच्छा CodeProject article भी है।

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

2

__stdcall कुछ कॉलिंग सम्मेलन को इंगित करता है (कुछ विवरणों के लिए this PDF देखें)। इसका अर्थ यह है कि यह निर्दिष्ट करता है कि फ़ंक्शन तर्क कैसे धक्का दिए जाते हैं और ढेर से पॉप किए जाते हैं, और कौन जिम्मेदार है।

__stdcall कई कॉलिंग सम्मेलनों में से एक है, और पूरे WINAPI में उपयोग किया जाता है। यदि आप फ़ंक्शन पॉइंटर्स को उन कार्यों में से कुछ के लिए कॉलबैक के रूप में प्रदान करते हैं तो आपको इसका उपयोग करना होगा। आम तौर पर, आपको अपने कोड में किसी भी विशिष्ट कॉलिंग सम्मेलन को इंगित करने की आवश्यकता नहीं है, लेकिन ऊपर उल्लिखित मामले को छोड़कर, केवल तीसरे पक्ष कोड को कॉलबैक प्रदान करने के अलावा, कंपाइलर के डिफ़ॉल्ट का उपयोग करें।

1

बस जब आप फ़ंक्शन कॉल करते हैं, तो इसे स्टैक/रजिस्टर में लोड किया जाता है। __stdcall एक सम्मेलन/रास्ता है (दाएं तर्क पहले, फिर तर्क छोड़ दिया ...), __decl एक और सम्मेलन है जिसका उपयोग स्टैक या रजिस्टरों पर फ़ंक्शन को लोड करने के लिए किया जाता है।

यदि आप उनका उपयोग करते हैं तो आप कंप्यूटर को लिंक करने के दौरान फ़ंक्शन को लोड/अनलोड करने के लिए उस विशिष्ट तरीके का उपयोग करने के लिए निर्देश देते हैं और इसलिए आपको कोई मेल नहीं मिला/क्रैश नहीं होगा।

अन्यथा फ़ंक्शन-कैली और फ़ंक्शन-कॉलर प्रोग्राम को क्रैश होने के कारण विभिन्न सम्मेलनों का उपयोग कर सकता है।

33

परंपरागत रूप से, सी फ़ंक्शन कॉल कॉलर के साथ कुछ पैरामीटर को स्टैक पर दबाकर, फ़ंक्शन को कॉल करने और फिर धक्का देने वाले तर्कों को साफ़ करने के लिए स्टैक को पॉप करने के साथ किए जाते हैं।

/* example of __cdecl */ 
push arg1 
push arg2 
push arg3 
call function 
add sp,12 // effectively "pop; pop; pop" 

नोट: ऊपर दिखाया गया डिफ़ॉल्ट सम्मेलन - __cdecl के रूप में जाना जाता है।

अन्य सबसे लोकप्रिय सम्मेलन __stdcall है। इसमें पैरामीटर को फिर से कॉलर द्वारा धक्का दिया जाता है, लेकिन स्टैक को कैली द्वारा साफ़ किया जाता है। यह Win32 एपीआई फ़ंक्शंस (जैसा कि WINAPI मैक्रो इन द्वारा परिभाषित किया गया है) के लिए मानक सम्मेलन है, और इसे कभी-कभी "पास्कल" कॉलिंग सम्मेलन भी कहा जाता है।

/* example of __stdcall */ 
push arg1 
push arg2 
push arg3 
call function // no stack cleanup - callee does this 

यह एक छोटी सी तकनीकी विस्तार की तरह लग रहा है, लेकिन अगर वहाँ कैसे ढेर फोन करने वाले और कॉल प्राप्त करने वाला के बीच किया जाता है पर असहमति है, ढेर एक तरीका है कि बरामद होने की संभावना नहीं है में नष्ट हो जाएगा। चूंकि __stdcall क्लीनअप को ढेर करता है, इसलिए यह कार्य करने के लिए (बहुत छोटा) कोड प्रत्येक कॉलर में डुप्लीकेट होने की बजाय केवल एक स्थान पर मिलता है, क्योंकि यह __cdecl में है। यह कोड को बहुत छोटा बनाता है, हालांकि आकार प्रभाव केवल बड़े कार्यक्रमों में दिखाई देता है।

printf() जैसे वैराडिक फ़ंक्शंस __stdcall के साथ सही होने के लिए लगभग असंभव हैं, क्योंकि केवल कॉलर वास्तव में जानता है कि उन्हें साफ़ करने के लिए कितने तर्क पारित किए गए थे। कैली कुछ अच्छे अनुमान लगा सकता है (कहें, प्रारूप स्ट्रिंग को देखकर), लेकिन स्टैक क्लीनअप को फ़ंक्शन के वास्तविक तर्क द्वारा निर्धारित किया जाना चाहिए, न कि कॉलिंग-कन्वेंशन तंत्र स्वयं। इसलिए केवल __cdecl विविध कार्यों का समर्थन करता है ताकि कॉलर सफाई कर सके।

लिंकर प्रतीक नाम सजावट: ऊपर एक बुलेट बिंदु में उल्लेख किया है, "गलत" सम्मेलन के साथ एक समारोह बुला, विनाशकारी हो सकता है तो माइक्रोसॉफ्ट एक तंत्र ऐसा होने से बचने के लिए है के रूप में। यह अच्छी तरह से काम करता है, हालांकि अगर कोई नहीं जानता कि कारण क्या हैं तो यह गड़बड़ हो सकता है। उन्होंने कॉलिंग कन्वेंशन को निम्न-स्तरीय फ़ंक्शन नामों में अतिरिक्त वर्णों (जिसे अक्सर "सजावट" कहा जाता है) के साथ एन्कोड करके इसे हल करने के लिए चुना है, और इन्हें लिंकर द्वारा असंबंधित नाम के रूप में माना जाता है। डिफ़ॉल्ट कॉलिंग सम्मेलन __cdecl है, लेकिन प्रत्येक व्यक्ति को स्पष्ट रूप से/जी के साथ अनुरोध किया जा सकता है? संकलक के लिए पैरामीटर।

__cdecl (सीएल/गोलों का अंतर ...)

इस प्रकार के सभी फ़ंक्शन नाम एक अंडरस्कोर लगी होती हैं, और क्योंकि फोन करने वाले ढेर सेटअप और ढेर सफाई के लिए जिम्मेदार है पैरामीटर की संख्या नहीं है वास्तव में बात। कॉलर और कैली के लिए वास्तव में पारित पैरामीटर की संख्या पर भ्रमित होना संभव है, लेकिन कम से कम स्टैक अनुशासन को ठीक से बनाए रखा जाता है।

__stdcall (सीएल/Gz ...)

ये फ़ंक्शन नाम एक अंडरस्कोर के साथ उपसर्ग और पारित मापदंडों के बाइट की संख्या से अधिक के साथ @ जोड़ दिए जाते हैं। इस तंत्र से, "गलत" प्रकार, या यहां तक ​​कि पैरामीटर की गलत संख्या के साथ फ़ंक्शन को कॉल करना संभव नहीं है।

__fastcall (सीएल/जीआर ...)

ये फ़ंक्शन नाम एक @ चिह्न के साथ शुरू और भी बहुत __stdcall की तरह, @parameter गिनती के साथ प्रत्यय कर रहे हैं।

उदाहरण:

Declaration      -----------------------> decorated name 


void __cdecl foo(void);   -----------------------> _foo 

void __cdecl foo(int a);   -----------------------> _foo 

void __cdecl foo(int a, int b); -----------------------> _foo 

void __stdcall foo(void);   -----------------------> [email protected] 

void __stdcall foo(int a);   -----------------------> [email protected] 

void __stdcall foo(int a, int b); -----------------------> [email protected] 

void __fastcall foo(void);   -----------------------> @[email protected] 

void __fastcall foo(int a);  -----------------------> @[email protected] 

void __fastcall foo(int a, int b); -----------------------> @[email protected] 
1

__stdcall बुला समारोह के लिए इस्तेमाल किया सम्मेलन है। यह कंपाइलर नियमों को बताता है जो स्टैक स्थापित करने, तर्कों को धक्का देने और वापसी मूल्य प्राप्त करने के लिए लागू होते हैं। __cdecl, __thiscall, __fastcall और __naked जैसे अन्य बुला सम्मेलनों के एक नंबर रहे हैं।

__stdcall Win32 सिस्टम कॉल के लिए मानक कॉलिंग सम्मेलन है।

अधिक जानकारी Wikipedia पर मिल सकती है।

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