c++ - __Stdcall का अर्थ और उपयोग क्या है?




windows calling-convention (6)

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

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

मैं इन दिनों __stdcall भर में आया हूँ।

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

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


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

रेमंड चेन ने प्रमुख x86 कॉलिंग सम्मेलनों के बारे में एक ब्लॉग लिखा, और वहां एक अच्छा कोडप्रोजेक्ट आलेख भी है।

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


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

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

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


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

/* 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 (सीएल / जीजे ...)

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

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

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

उदाहरण:

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]

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


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

खिड़कियों पर सबसे लोकप्रिय कॉलिंग सम्मेलन हैं

  • stdcall
  • cdecl
  • clrcall
  • fastcall
  • thiscall

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

कॉलिंग सम्मेलन यहां दस्तावेज हैं

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





calling-convention