2009-06-02 14 views
5

मैं यह निर्धारित करने में सक्षम होना चाहूंगा कि पॉइंटर स्टैक पर है या नहीं, कई कारणों से रनटाइम पर। जैसे कि मैं इसे फ़ंक्शन कॉल में पास करता हूं, मैं यह निर्धारित कर सकता हूं कि मुझे इसे क्लोन करने की आवश्यकता है या नहीं। या मुझे इसे हटाने की जरूरत है या नहीं।सी ++/सी ऑब्जेक्ट-> isOnStack()

माइक्रोस्कोफ्ट सी (वीसी 6,7,8) में एक संकेतक को जांचने के लिए एक तरीका है कि यह स्टैक पर है या नहीं? मैं केवल थ्रेड पर यह निर्धारित करने के लिए चिंतित हूं कि ऑब्जेक्ट पर रखा गया ढेर है।

तरह

स्थिर स्थिरांक पूर्णांक __stack_size और __stack_top

कुछ ???? धन्यवाद!

+3

तरफ से "विधानसभा में ड्रॉप और वहाँ जाँच" मेरे लिए स्पष्ट में कोई जवाब नहीं। इसके अलावा, सवाल यह सुझाव देने के लिए काफी अजीब है कि आप कुछ अनावश्यक रूप से अजीब कर रहे हैं। शायद गलत भी। अच्छी मदद पाने की संभावना बढ़ जाती है यदि आप थोड़ा सा विस्तार करते हैं ... – dmckee

+0

ऐसा करने के लिए कारणों से आपको अपनी समस्या का असली समाधान मिल सकता है ... जब तक आप और अधिक नहीं पूछते हैं तब तक स्टैक ओवरव्लो वास्तव में इसके साथ मदद नहीं करता सामान्य प्रश्न जैसे 'ऐसा करने का एक बेहतर तरीका है'। – Kieveli

+0

आपको स्मार्ट पॉइंटर्स और संदर्भ पास करने की आवश्यकता है। ऐसा लगता है कि आप एक और भाषा से प्रतिमान लाने की कोशिश कर रहे हैं जो सी ++ दुनिया में फिट नहीं है। किसी ऑब्जेक्ट के उपयोगकर्ता को यह ध्यान नहीं दिया जाना चाहिए कि इसे आवंटित किया गया है। यदि आप संदर्भ द्वारा ऑब्जेक्ट पास में हेरफेर करना चाहते हैं। यदि आप स्वामित्व लेना चाहते हैं तो auto_ptr पास करें। यदि आप साझाकरण को साझा नहीं करते हैं तो एक साझा_ptr –

उत्तर

3

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

उदाहरण के लिए, फास्टकॉल में, एक या अधिक तर्क रजिस्ट्रार के माध्यम से पारित किए जा सकते हैं। See MSDN for more. यह पता लगाने के लिए किसी भी योजना को गड़बड़ कर देगा कि कोई पता किसी निश्चित सीमा के भीतर मौजूद है या नहीं। एमएस के इस स्कॉल में, यह सूचक रजिस्ट्रार के माध्यम से पारित किया जाता है। & यह स्टैक के आरंभ और अंत के बीच मूल्यों की एक श्रृंखला के बीच कहीं भी हल नहीं होगा।

नीचे पंक्ति, शोध कॉलिंग सम्मेलन, यह निर्दिष्ट करता है कि कैसे स्टैक मेमोरी निर्धारित की जाएगी। यहां एक good tutorial

नोट यह बहुत ही प्लेटफार्म विशिष्ट है!

+0

मुझे लगता है कि वह जानना चाहता है कि ऑब्जेक्ट पॉइंटर द्वारा इंगित किया गया है या नहीं ढेर, असली सूचक खुद नहीं। उस मामले में मुझे नहीं लगता कि कॉलिंग सम्मेलन का कोई फर्क नहीं पड़ता क्योंकि ऑब्जेक्ट्स शायद ही कभी (यदि कभी?) रजिस्टरों में पास हो जाते हैं - केवल सूचक ही होगा। – DougN

+0

मुझे विश्वास नहीं है कि स्टैक में मेमोरी का लेआउट यह निर्धारित करने की विधि को प्रभावित करेगा कि एक चर ढेर या ढेर पर है या नहीं। यह एक सी ++ प्रश्न है, इसलिए आप पूरे सीडीसीएल कॉल की उम्मीद करेंगे। – Kieveli

+0

cdecl का उपयोग विधियों के लिए नहीं किया जाएगा जहां यह सूचक शामिल है। –

7

दिलचस्प सवाल।

यहां यह निर्धारित करने का एक विचार है कि इसे कैसे निर्धारित किया जाए, लेकिन फ़ंक्शन कॉल नहीं। ढेर पर अपने आवेदन की शुरुआत में एक डमी चर बनाएँ। फ़ंक्शन में स्टैक पर एक चर बनाएँ InStack (void * ptr) यह देखने के लिए जांचें कि 'ptr' डमी चर और स्थानीय चर के बीच है।

याद रखें कि स्टैक किसी दिए गए धागे के लिए संगत है। मुझे यकीन नहीं है कि जब आप इस जानकारी के लिए एक धागे से दूसरी तरफ जांचना शुरू करेंगे तो क्या होगा।

यदि यह ढेर में नहीं है, तो यह ढेर पर होना चाहिए।

+0

+1 यह काफी अच्छा समाधान है, लेकिन निश्चित रूप से यह अयोग्य है। –

+1

और रजिस्टरों में तर्क लोड करने वाले सम्मेलनों को कॉल करने के लिए काम नहीं करेगा। –

+0

@ इरंबिलानजा: क्या आप विस्तारित कर सकते हैं कि यह पोर्टेबल क्यों नहीं है? एक ढेर की कार्यक्षमता अनुक्रमिक होने वाले पते पर निर्भर करती है, इसलिए मैं उम्मीद करता हूं कि यह सभी प्रणालियों पर काम करे। –

5

मुझे यह निर्धारित करने के लिए कोई विधि नहीं है कि ऑब्जेक्ट आवंटित किया गया था।

मुझे लगता है कि इस तरह के व्यवहार से बचा जाना चाहिए। उपयोगकर्ता और लाइब्रेरी डेवलपर के बीच अनुबंध द्वारा ऐसी चीजों को हल किया जाना चाहिए। दस्तावेजों में इन चीजों को बताओ! यदि अनिश्चित वस्तु को प्रतिलिपि बनाएँ (जिसके लिए एक प्रतिलिपि बनाने की आवश्यकता है और आपको अवांछित वस्तुओं की प्रतिलिपि बनाने की कोशिश करने से बचाता है)।

आप बूस्ट से smart pointers का भी उपयोग कर सकते हैं। यदि किसी ऑब्जेक्ट की अब आवश्यकता होने पर अनिश्चित है, तो उसे साझा पॉइंटर के रूप में पास करें।

+0

प्रश्न के लिए अच्छा जवाब नहीं पूछा गया! – Kieveli

+2

+1 जंगल को देखने के लिए, सिर्फ पेड़ नहीं। :- डी –

+0

यह लोगों के बीच सामान्य अंतर है और उन्हें वास्तव में क्या चाहिए। – ebo

9

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

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

कोई संकेतक नहीं है कि पॉइंटर क्या इंगित करता है, और किसी भी गैर-मानक तरीके से तोड़ने की संभावना है। आप स्टैक संगतता पर विशेष रूप से मल्टीथ्रेड किए गए अनुप्रयोगों में भरोसा नहीं कर सकते हैं (और कोई भी परिणाम को महसूस किए बिना किसी एप्लिकेशन को आसानी से थ्रेड जोड़ सकता है)।

एकमात्र सुरक्षित तरीके एक कॉलिंग सम्मेलन होना है कि बुलाया गया कार्य एक पारित वस्तु को हटा देगा या नहीं करेगा, या किसी प्रकार का स्मार्ट पॉइंटर पास करेगा। कुछ और परेशानी के लिए पूछ रहा है।

+1

+1 "आपको सभी ढेर पॉइंटर्स को हटाने की कोशिश नहीं करनी चाहिए।" स्वामित्व उस से अधिक कड़ाई से नियंत्रित किया जाना चाहिए। –

0

यह बहुत ही मंच विशिष्ट है, और आईएमओ केवल डीबग बिल्ड डायग्नोस्टिक्स के लिए उपयुक्त है। आपको क्या करना होगा (WIntel पर) यह है:

जब कोई धागा बनाया जाता है, तो एक स्टैक वैरिएबल बनाएं, और अपना पता वैश्विक (थ्रेडिड, स्टैक बेस एड्रेस) मानचित्र में संग्रहीत करें।

IsOnStack को अपना स्थानीय चर बनाने की आवश्यकता है, और जांचें कि पॉइंटर पारित स्टैक बेस और वर्तमान स्टैक फ्रेम में पता के बीच है या नहीं।

यह आपको अन्य धागे के भीतर abotu चर कुछ भी नहीं बताएगा। स्टैक पते कम हो जाते हैं, इसलिए आधार पता वर्तमान पते से अधिक है।


एक पोर्टेबल समाधान के रूप में, मैं एक बढ़ावा :: shared_ptr है, जो एक Deleter साथ जुड़ा हो सकता दे देते हैं। (बढ़ावा में, यह एक टेम्पलेट पैरामीटर नहीं है, इसलिए यह पॉइंटर उपभोग करने वाले फ़ंक्शन को "संक्रमित नहीं करता")।

आप इस तरह एक "अप्रबंधित" सूचक बना सकते हैं:

inline void boost_null_deleter(void *) {} 

template <typename T> inline 
boost::shared_ptr<T> unmanaged_ptr(T * x) 
{ 
    return boost::shared_ptr<T>(x, ::boost_null_deleter); 
} 

और इस

Foo local = { ... }; 
FooPtr heapy(new Foo); 

FunnyFunc(unmanaged_ptr(&local)); 
FunnyFunc(heapy); 
0

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

0

खैर, मैं मानता हूं कि आप जो करने की कोशिश कर रहे हैं, वह संभवतः एक बेहतर तरीका है। लेकिन यह वैसे भी एक दिलचस्प सवाल है। तो चर्चा के लिए ...

सबसे पहले, पोर्टेबल सी या सी ++ करने का कोई तरीका नहीं है। कम से कम asm{ } ब्लॉक का उपयोग करके आपको असेंबली में जाना होगा।

दूसरा, मैं इसे उत्पादन कोड में उपयोग नहीं करता। लेकिन वीसी ++/x86 के लिए आप यह पता लगा सकते हैं कि कोई चर पर स्टैक द्वारा चेक किया गया है कि यह पता ईएसपी और ईबीपी रजिस्टरों के मानों के बीच है।

आपका ईएसपी (विस्तारित स्टैक पॉइंटर, कम मूल्य) आपके स्टैक के शीर्ष और ईबीपी (विस्तारित बेस पॉइंटर) आमतौर पर नीचे होता है। X86 पर Structure of the Call Stack यहां दिया गया है।

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

चीजें जो फेंकती हैं संकलक अनुकूलन हैं। आपका कंपाइलर फ्रेम पॉइंटर (ईबीपी) छोड़ सकता है। वीसी ++ में यह -Oy flag है। तो बेस पॉइंटर के रूप में ईबीपी का उपयोग करने के बजाय आप फ़ंक्शन पैरामीटर के पते का उपयोग कर सकते हैं, यदि आपके पास कोई है। चूंकि उन ढेर पर थोड़ा ऊपर है।

लेकिन क्या होगा यदि आप जिस वैरिएबल का परीक्षण कर रहे हैं वह आपके कॉलर के ढेर पर है? या एक कॉलर की ढेर आपके ऊपर कई पीढ़ियों? खैर आप पूरे कॉल स्टैक पर चल सकते हैं, लेकिन आप देख सकते हैं कि यह कितना बदसूरत हो सकता है (जैसा कि यह पहले से नहीं है :-))

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

इसके बारे में पता ढेर पर क्या और भी बदतर है ....

0

कुछ प्लेटफार्मों पर, ढेर रन-टाइम प्रणाली द्वारा विभाजित किया जा सकता। यही है, एक (कोई भी इरादा नहीं है) स्टैक ओवरफ़्लो प्राप्त करने के बजाय, सिस्टम स्वचालित रूप से कुछ और स्टैक स्पेस पकड़ लेता है। बेशक, नई स्टैक स्पेस आमतौर पर पुरानी स्टैक स्पेस के साथ संगत नहीं होती है।

इसलिए यह वास्तव में सुरक्षित नहीं है कि स्टैक पर कुछ है या नहीं।

auto_ptr का उपयोग आम तौर पर इस तरह की चीज़ की आवश्यकता को समाप्त करता है, और इसके अलावा कूलर भी है।

0

एमएसवीसी विंडोज कंपाइलर विशिष्ट उत्तर। ऑब्जेक्ट में मौजूद थ्रेड के लिए यह निश्चित रूप से विशिष्ट है।यह एक बहुत बुरा विचार है अन्य की तुलना में एक कौन ढेर यह है, इसलिए मुझे लगता है कि :)

bool __isOnStack (स्थिरांक शून्य * ptr)
{
के बारे में चिंतित नहीं हूँ पर किसी भी थ्रेड में किसी भी स्वत: ढेर आइटम पारित करने के लिए

  • // एफएस: [0x04] 4 Win9x और NT ढेर
    // एफएस के शीर्ष पर: [0x08] 4 Win9x और ढेर
    स्थिरांक चार की NT वर्तमान नीचे * रोक;
    कॉन्स चार * एसबीओटी;
    __asm ​​{
    mov EAX, एफएस: [04h]
    mov [रोक], EAX
    mov EAX, एफएस: [08h]
    mov [sBot], EAX

    }
    वापसी (एसटीओपी> ((कॉन्स char *) पीआरटी) & & ((कॉन्स चार *) पीआरटी)> एसबीओटी);

}