दिलचस्प पोस्ट
जावास्क्रिप्ट: कैसे $ लिखने के लिए (दस्तावेज़)। jquery बिना घटना की तरह मैं पर्ल में एक सरणी से डुप्लिकेट आइटम कैसे निकालूं? पटरियों: शामिल बनाम: जुड़ती है पांड्या: डेटाफ्रेम के उपनिर्देशक: प्रतियां बनाम विचार अगर ऑब्जेक्ट एक jQuery ऑब्जेक्ट है, तो जांचें एनएसपीडेट: एनएसडीटे की संपत्ति के दिन वस्तुओं को छानने के लिए यूडीआईडी ​​और रिंकम्पलेशन के प्रबंधन के बिना आईओएस एप्लीकेशन को वायरलेस तरीके से कैसे वितरित करें I मेरी PHP ऐप 404 त्रुटि क्यों नहीं भेजेगी? सी ++ में लंबी दोहरी की सटीकता क्या है? कैसे zlib, gzip और ज़िप संबंधित हैं? क्या वे आम में है और वे कैसे अलग हैं? पुरालेख भेजने पर एक्सकोड 6 दुर्घटनाएं JTable राइट संरेखित हेडर MySQL में varchar फ़ील्ड संख्यात्मक रूप से छंटनी एंड्रॉइड ओवरराइड ऑन बैकडप्रेस () एलडीएपी क्वेरी कैसे लिखूं यह जांचने के लिए कि उपयोगकर्ता समूह का सदस्य है या नहीं?

कैसे पता कैसे एक संकेतक ढेर या स्टैक को इंगित करता है?

उदाहरण:

bool isHeapPtr(void* ptr) { //... } int iStack = 35; int *ptrStack = &iStack; bool isHeapPointer1 = isHeapPtr(ptrStack); // Should be false bool isHeapPointer2 = isHeapPtr(new int(5)); // Should be true /* I know... it is a memory leak */ 

क्यों, मैं यह जानना चाहता हूं:

यदि मेरे पास एक क्लास में एक सदस्य-सूचक होता है और मुझे नहीं पता है कि इंगित करने का ऑब्जेक्ट नया-आवंटित है। तो मुझे इस तरह की उपयोगिता का पता होना चाहिए कि मुझे संकेतक delete है या नहीं।

परंतु:
मेरे डिजाइन अभी तक नहीं किए गए हैं इसलिए, मैं इस तरह से कार्यक्रम को हमेशा इसे delete होगा। मैं बकवास प्रोग्रामिंग से बचने जा रहा हूं

वेब के समाधान से एकत्रित समाधान "कैसे पता कैसे एक संकेतक ढेर या स्टैक को इंगित करता है?"

ऐसा करने का कोई तरीका नहीं है – और अगर आपको यह करने की आवश्यकता है, तो आपके डिज़ाइन में कुछ गड़बड़ है इस बारे में चर्चा है कि आप इसे और अधिक प्रभावी C ++ में क्यों नहीं कर सकते।

सामान्य मामले में, आप भाग्य से बाहर हैं, मैं डरता हूं – चूंकि पॉइंटर्स के पास कोई मूल्य हो सकता है, उन्हें अलग बताओ करने का कोई रास्ता नहीं है। यदि आपको अपने स्टैक प्रारंभ पता और आकार (उदाहरण के लिए एक एम्बेडेड ऑपरेटिंग सिस्टम में अपने टीसीबी से) का ज्ञान था, तो आप ऐसा करने में सक्षम हो सकते हैं कुछ इस तरह:

 stackBase = myTCB->stackBase; stackSize = myTCB->stackSize; if ((ptrStack < stackBase) && (ptrStack > (stackBase - stackSize))) isStackPointer1 = TRUE; 

मैं सोच सकता हूं कि केवल "अच्छा" समाधान उस कक्षा के लिए अधिभार operator new और इसे ट्रैक करें। ऐसा कुछ (मस्तिष्क संकलित कोड):

 class T { public: void *operator new(size_t n) { void *p = ::operator new(n); heap_track().insert(p); return p; } void operator delete(void* p) { heap_track().erase(p); ::operator delete(p); } private: // a function to avoid static initialization order fiasco static std::set<void*>& heap_track() { static std::set<void*> s_; return s_; } public: static bool is_heap(void *p) { return heap_track().find(p) != heap_track().end(); } }; 

तो आप इस तरह सामान कर सकते हैं:

 T *x = new X; if(T::is_heap(x)) { delete x; } 

हालांकि, मैं एक डिजाइन के खिलाफ सलाह देता हूं जिसके लिए आपको यह पूछने में सक्षम होना चाहिए कि क्या ढेर पर कुछ आवंटित किया गया है।

खैर, अपने कोडांतरक पुस्तक को बाहर निकालें, और स्टोक-पॉइंटर पर अपने सूचक के पते की तुलना करें:

 int64_t x = 0; asm("movq %%rsp, %0;" : "=r" (x) ); if ( myPtr < x ) { ...in heap... } 

अब एक्स में वह पता होगा जिसमें आपको अपने पॉइंटर से तुलना करना होगा। ध्यान दें कि यह किसी अन्य थ्रेड में आवंटित स्मृति के लिए काम नहीं करेगा, क्योंकि इसकी अपनी स्टैक होगी।

यहां यह है, एमएसवीसी के लिए काम करता है:

 #define isheap(x, res) { \ void* vesp, *vebp; \ _asm {mov vesp, esp}; \ _asm {mov vebp, ebp}; \ res = !(x < vebp && x >= vesp); } int si; void func() { int i; bool b1; bool b2; isheap(&i, b1); isheap(&si, b2); return; } 

यह थोड़ा बदसूरत है, लेकिन काम करता है केवल स्थानीय चर के लिए काम करता है अगर आप कॉलिंग फंक्शन से स्टैक पॉइंटर को पास करते हैं तो मैक्रो सच वापस आएगा (इसका मतलब है कि यह ढेर है)

सबसे पहले, आपको यह जानने की आवश्यकता क्यों है? क्या वास्तविक समस्या आप हल करने की कोशिश कर रहे हैं?

इस तरह के दृढ़ संकल्प को बनाने के बारे में मैं जानता हूं कि एकमात्र तरीका वैश्विक operator new और operator delete । उसके बाद आप अपनी मेमोरी मैनेजर से पूछ सकते हैं कि एक पॉइंटर (हीप) से संबंधित है या नहीं (स्टैक या वैश्विक डाटा)।

यहां तक ​​कि अगर आप यह निर्धारित कर सकते हैं कि कोई सूचक एक विशेष ढेर या एक विशेष ढेर पर था, तो एक ही आवेदन के लिए कई ढेर और कई स्टैक हो सकते हैं।

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

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

बेशक स्मार्ट पॉइंटर्स यहां महत्वपूर्ण हैं – यदि आप एक स्वामित्व-ट्रैकिंग पॉइंटर चाहते हैं, तो मुझे यकीन है कि आप स्मार्ट पॉइंटर प्रकार ढूँढ सकते हैं या लिख ​​सकते हैं कि परेशानी दूर है।

मुख्य धारा के ऑपरेटिंग सिस्टम में, ढेर ऊपर से बढ़ता है जबकि ढेर नीचे से बढ़ता है। तो आप ये देख सकते हैं कि "बड़े" की कुछ परिभाषा के लिए पता बड़ा मूल्य से परे है या नहीं। उदाहरण के लिए, मेरे 64-बिट लिनक्स सिस्टम पर निम्न काम करता है:

 #include <iostream> bool isHeapPtr(const void* ptr) { return reinterpret_cast<unsigned long long int>(ptr) < 0xffffffffull; } int main() { int iStack = 35; int *ptrStack = &iStack; std::cout << isHeapPtr(ptrStack) << std::endl; std::cout << isHeapPtr(new int(5)) << std::endl; } 

ध्यान दें कि एक क्रूड अनुमानी है जो कि खेलना दिलचस्प हो सकता है, लेकिन उत्पादन कोड के लिए उपयुक्त नहीं है

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

एक और अधिक आम तरीका यह है कि अगर मैं बफर को आवंटित करता हूं, तो मुझे इसे हटा देना होगा, यदि प्रोग्राम मुझे बफर पास करता है, तो इसे हटाने की मेरी ज़िम्मेदारी नहीं है I

जैसे

 class CSomething { public: CSomething() : m_pBuffer(new char[128]) , m_bDeleteBuffer(true) { } CSomething(const char *pBuffer) : m_pBuffer(pBuffer) , m_bDeleteBuffer(false) { } ~CSomething() { if (m_bDeleteBuffer) delete [] m_pBuffer; } private: const char *m_pBuffer; bool m_bDeleteBuffer; }; 

आप इसे कठिन तरीके से करने की कोशिश कर रहे हैं अपने डिजाइन को स्पष्ट करें ताकि यह स्पष्ट हो कि कौन "डेटा" का उपयोग करता है और उस कोड को अपने जीवनकाल के साथ सौंपें

यहां टिप का उपयोग करते हुए विंडोज़ में ऐसा करने का सार्वभौमिक तरीका है:

 bool isStack(void* x) { void* btn, *top; _asm { mov eax, FS:[0x08] mov btn, eax mov eax, FS:[0x04] mov top, eax } return x < top && x > btn; } void func() { int i; bool b1; bool b2; b1 = isStack(&i); b2 = isStack(&si); return; } 

यह अर्ध-मज़बूती से करने का एकमात्र तरीका है, यदि आप उस प्रकार के लिए operator new को अधिभार कर सकते हैं जिसके लिए आपको यह करने की आवश्यकता है। दुर्भाग्य से वहाँ कुछ प्रमुख नुकसान हैं और मुझे याद नहीं है कि वे क्या कर रहे हैं।

मुझे पता है कि एक खाई यह है कि ढेर पर कुछ सीधे सीधे आवंटित किए बिना हो सकता है उदाहरण के लिए:

 class A { int data; }; class B { public: A *giveMeAnA() { return &anA; } int data; A anA; }; void foo() { B *b = new B; A *a = b->giveMeAnA(); } 

उपरोक्त कोड में a foo एक पॉइंटर के साथ उस ढेर पर ऑब्जेक्ट तक समाप्त होता है जिसे new साथ आवंटित नहीं किया गया था। यदि आपका सवाल वाकई में है "मैं कैसे जानूं कि मैं इस सूचक को delete सकता हूं।" कुछ operator new करने के लिए operator new ओवरलोड करने से आपको उस प्रश्न का उत्तर देने में मदद मिल सकती है। मैं अभी भी सोचता हूं कि यदि आपको उस सवाल पूछना है जो आपने बहुत गलत किया है

आप कैसे नहीं जानते कि कुछ ढेर-आवंटित है या नहीं? आपको सॉफ़्टवेयर को एक ही बिंदु आवंटन के लिए डिजाइन करना चाहिए।

जब तक आप किसी एम्बेडेड डिवाइस में कुछ वास्तविक विदेशी सामान नहीं कर रहे हैं या कस्टम कर्नेल में गहन काम कर रहे हैं, तो मुझे इसकी ज़रूरत नहीं है।

इस कोड को देखें (उदाहरण के लिए कोई त्रुटि जांच नहीं):

 class A { int *mysweetptr; A() { mysweetptr = 0; //always 0 when unalloc'd } void doit() { if( ! mysweetptr) { mysweetptr = new int; //now has non-null value } } void undoit() { if(mysweetptr) { delete mysweetptr; mysweetptr = 0; //notice that we reset it to 0. } } bool doihaveit() { if(mysweetptr) return true; else return false; } ~A() { undoit(); } }; 

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

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