c++ - हटाए गए पॉइंटर के साथ विज़ुअल स्टूडियो क्या करता है और क्यों?




pointers visual-studio-2012 (4)

इसमें यह भी कहा गया है कि पॉइंटर को उसी स्थान पर इंगित करना जारी रखा जाएगा जब तक कि इसे पुन: असाइन या NULL में सेट नहीं किया जाता है।

यह निश्चित रूप से भ्रामक जानकारी है।

स्पष्ट रूप से वह पता जिसे सूचक डिलीट होने पर बदलावों की ओर इशारा करता है!

ये क्यों हो रहा है? यह विशेष रूप से Visual Studio के साथ कुछ करने के लिए है?

यह स्पष्ट रूप से भाषा विनिर्देशों के भीतर है। delete लिए कॉल के बाद ptr मान्य नहीं है। इसे delete जाने के बाद ptr का उपयोग करना अपरिभाषित व्यवहार का कारण है। यह मत करो। delete करने के लिए कॉल के बाद ptr साथ जो भी करना है, वह रन टाइम एनवायरनमेंट फ्री है।

और यदि डिलीट किया गया पता बदल सकता है तो यह किसी भी ओर इशारा कर रहा है, क्यों कुछ स्वचालित रैंडम के बजाय NULL के लिए पॉइंटर को स्वचालित रूप से सेट नहीं करेगा ???

सूचक के मूल्य को किसी भी पुराने मूल्य में बदलना भाषा विनिर्देश के भीतर है। जहाँ तक इसे NULL में बदलने की बात है, मैं कहूँगा कि यह बुरा होगा। यदि सूचक NULL के लिए सेट किया गया था, तो प्रोग्राम अधिक सेंस तरीके से व्यवहार करेगा। हालाँकि, यह समस्या को छिपाएगा। जब कार्यक्रम को अलग-अलग अनुकूलन सेटिंग्स के साथ संकलित किया जाता है या एक अलग वातावरण में पोर्ट किया जाता है, तो समस्या संभवतः सबसे असंगत क्षण में दिखाई देगी।

एक C ++ पुस्तक मैं पढ़ रहा हूं कि जब कोई पॉइंटर delete ऑपरेटर का उपयोग करके मेमोरी को डिलीट कर देता है तो वह जिस स्थान पर इंगित करता है वह "फ्रीड" है और इसे अधिलेखित किया जा सकता है। इसमें यह भी कहा गया है कि पॉइंटर को उसी स्थान पर इंगित करना जारी रखा जाएगा जब तक कि इसे पुन: असाइन या NULL सेट नहीं किया जाता NULL

विज़ुअल स्टूडियो 2012 में हालांकि; यह मामला प्रतीत नहीं होता है!

उदाहरण:

#include <iostream>

using namespace std;

int main()
{
    int* ptr = new int;
    cout << "ptr = " << ptr << endl;
    delete ptr;
    cout << "ptr = " << ptr << endl;

    system("pause");

    return 0;
}

जब मैं इस कार्यक्रम को संकलित करता हूं और चलाता हूं तो मुझे निम्नलिखित आउटपुट मिलते हैं:

ptr = 0050BC10
ptr = 00008123
Press any key to continue....

स्पष्ट रूप से वह पता जिसे सूचक डिलीट होने पर बदलावों की ओर इशारा करता है!

ये क्यों हो रहा है? यह विशेष रूप से Visual Studio के साथ कुछ करने के लिए है?

और यदि डिलीट किया गया पता बदल सकता है तो यह वैसे भी इंगित कर रहा है, तो कुछ यादृच्छिक पते के बजाय NULL को पॉइंटर स्वचालित रूप से सेट क्यों नहीं करेगा?


आप /sdl संकलन विकल्प के दुष्प्रभाव देखते हैं। VS2015 परियोजनाओं के लिए डिफ़ॉल्ट रूप से चालू, यह अतिरिक्त सुरक्षा जांच को सक्षम करता है जो कि / gs द्वारा प्रदान की जाती है। प्रोजेक्ट> गुण> C / C ++> General> SDL चेक सेटिंग को बदलने के लिए उपयोग करें।

MSDN लेख से उद्धरण:

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

ध्यान रखें कि जब आप MSVC का उपयोग करते हैं तो NULL को हटाए गए पॉइंटर्स सेट करना एक बुरा अभ्यास है। यह आपको डीबग हीप और इस / sdl ऑप्शन दोनों से मिलने वाली मदद को पराजित करता है, अब आप अपने प्रोग्राम में अवैध फ्री / डिलीट कॉल का पता नहीं लगा सकते हैं।


मेरा मानना ​​है कि, आप किसी प्रकार का डिबग मोड चला रहे हैं और वीएस आपके पॉइंटर को किसी ज्ञात स्थान पर पुन: स्थापित करने का प्रयास कर रहा है, ताकि आगे इसे हटाने की कोशिश की जा सके। रिलीज मोड में एक ही कार्यक्रम को संकलित / चलाने का प्रयास करें।

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

वास्तव में, जितना अधिक मैं इसके बारे में सोचता हूं, उतना ही मुझे लगता है कि ऐसा करते समय वीएस गलती पर है। क्या होगा अगर पॉइंटर कांस्टेबल है? क्या यह अभी भी इसे बदलने वाला है?


मैंने देखा कि ptr में संग्रहीत पता हमेशा 00008123 साथ ओवरराइट किया जा रहा था ...

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

... NULL के लिए चेक एक सामान्य कोड निर्माण है जिसका अर्थ है कि NULL के लिए एक मौजूदा चेक NULL के साथ संयुक्त रूप से एक संकरण मूल्य के रूप में संयुक्त रूप से एक वास्तविक मेमोरी सुरक्षा मुद्दे को छिपा सकता है जिसका मूल कारण वास्तव में पते की आवश्यकता है।

इस कारण से हमने 0x8123 को एक स्वच्छता मूल्य के रूप में चुना है - एक ऑपरेटिंग सिस्टम के नजरिए से यह शून्य पते (NULL) के रूप में एक ही मेमोरी पेज में है, लेकिन 0x8123 पर एक एक्सेस उल्लंघन बेहतर रूप से डेवलपर को अधिक विस्तृत ध्यान देने की आवश्यकता है। ।

इतना ही नहीं यह बताता है कि विज़ुअल स्टूडियो पॉइंटर को हटाने के बाद क्या करता है, यह भी जवाब देता है कि उन्होंने इसे NULL स्वचालित रूप से सेट करने के लिए क्यों नहीं चुना!

यह "फ़ीचर" "एसडीएल चेक" सेटिंग के हिस्से के रूप में सक्षम है। इसे सक्षम / अक्षम करने के लिए: PROJECT -> गुण -> कॉन्फ़िगरेशन गुण -> C / C ++ -> सामान्य -> ​​SDL जाँच

इसकी पुष्टि करने के लिए:

इस सेटिंग को बदलना और समान कोड को फिर से लिखना निम्न आउटपुट का उत्पादन करता है:

ptr = 007CBC10
ptr = 007CBC10

"सुविधा" उद्धरण में है क्योंकि ऐसे मामले में जहां आपके पास एक ही स्थान पर दो पॉइंटर्स हैं, कॉल हटाना केवल उनमें से एक को पवित्र करेगा। अन्य को अमान्य स्थान की ओर संकेत करते हुए छोड़ दिया जाएगा।

विज़ुअल स्टूडियो आपको इसके डिज़ाइन में इस दोष का दस्तावेजीकरण करने में विफल होकर एक चिपचिपी स्थिति के लिए स्थापित कर सकता है।






delete-operator