ऐसे वेलग्रिंड के रूप में विशेष संकलक समर्थन, गैर दखल स्मृति डिबगर के बिना फ्रेम कि क्षेत्र से बाहर चले गए हैं ढेर करने के लिए उपयोग का पता लगा सकते में , लेकिन कार्यों के भीतर scopes नहीं है। ऐसा इसलिए है क्योंकि संकलक (आमतौर पर) allocate all the memory for a stack frame in a single pass *। इसलिए एक ही फ़ंक्शन के भीतर स्कोप चर के बाहर पहुंच का पता लगाने के लिए, हमें "जहर" चर के लिए विशिष्ट कंपाइलर उपकरण की आवश्यकता होती है जो दायरे से बाहर हो गया है लेकिन जिसका संलग्न फ्रेम अभी भी मान्य है।
तकनीक ubsan AddressSanitizer, बजना और जीसीसी के हाल के संस्करणों में उपलब्ध द्वारा इस्तेमाल किया, replace stack access with access to specially allocated memory के लिए है:
आदेश में ढेर स्मृति के लिए लागू करने के लिए संगरोध हम ढेर करने के लिए ढेर को बढ़ावा देने की जरूरत है। [...] __asan_stack_malloc(real_stack, frame_size)
थ्रेड-स्थानीय ढेर जैसी संरचना (नकली ढेर) से नकली फ्रेम (फ्रेम_साइज बाइट्स) आवंटित करता है। प्रत्येक नकली फ्रेम असुविधाजनक आता है और फिर रेडज़ोन को वाद्य यंत्र कोड में जहर दिया जाता है। __asan_stack_free(fake_stack, real_stack, frame_size)
पूरे नकली फ्रेम को जहर देता है और इसे हटा देता है। उपयोग और उत्पादन के
उदाहरण:
$ g++ -std=c++11 a.cpp -fsanitize=address && env ASAN_OPTIONS='detect_stack_use_after_return=1' ./a.out
ERROR: AddressSanitizer: stack-use-after-scope on address 0x7fd0e8300020 at pc 0x000000400c1b bp 0x7fff5b45ecf0 sp 0x7fff5b45ece8
READ of size 4 at 0x7fd0e8300020 thread T0
#0 0x400c1a in main (a.out+0x400c1a)
#1 0x7fd0ebe18d5c in __libc_start_main (/lib64/libc.so.6+0x1ed5c)
#2 0x400a48 (a.out+0x400a48)
Address 0x7fd0e8300020 is located in stack of thread T0 at offset 32 in frame
#0 0x400b26 in main (a.out+0x400b26)
This frame has 1 object(s):
[32, 36) 'b' <== Memory access at offset 32 is inside this variable
ध्यान दें कि क्योंकि यह महंगा है यह संकलन समय (-fsanitize=address
) और रन टाइम पर (ASAN_OPTIONS='detect_stack_use_after_return=1'
) में दोनों अनुरोध किया जाना चाहिए। न्यूनतम संस्करणों के बारे में; यह जीसीसी 7.1.0 और क्लैंग ट्रंक के साथ काम करता है, लेकिन स्पष्ट रूप से क्लैंग के किसी भी रिलीज़ संस्करण नहीं है, इसलिए यदि आप एक रिलीज कंपाइलर का उपयोग करना चाहते हैं तो आपको जीसीसी का उपयोग करना होगा।
* पर विचार करें कि इन दोनों कार्यों (-O0
पर जीसीसी द्वारा जैसे) संकलन समान मशीन कोड के लिए, इसलिए वहाँ कोई रास्ता नहीं है ** एक गैर दखल स्मृति डिबगर के लिए उन दोनों के बीच अंतर बताने में:
int f() {
int* a;
{
int b = 42;
a = &b;
}
return *a;
}
int g() {
int* a;
int b = 42;
a = &b;
return *a;
}
** कड़ाई से बोलते हुए, यदि डीबग प्रतीकों उपलब्ध हैं तो डीबगर उपलब्ध चर और बाहर जाने वाले चर ट्रैक कर सकता है। लेकिन आम तौर पर यदि आपके पास डीबग प्रतीकों उपलब्ध हैं तो आपके पास स्रोत कोड है, इसलिए प्रोग्राम को उपकरण के साथ पुन: संकलित कर सकते हैं।
मैं शर्त लगाता हूं कि शुद्धता करता है, लेकिन मुझे नहीं पता कि यह अब और कितना है कि वालग्रिंड और अन्य कम-मुक्त-मुक्त उपकरण बढ़ गए हैं। –
सी और सी ++ एक ही भाषा नहीं हैं।वे इन दिनों बहुत अलग हैं। शायद गुजरता – tambre
@ FrançoisAndrieux * प्रश्न उपकरण के लिए पूछ स्टैक ओवरफ़्लो पर विषय * लेकिन एक सरल rephrase "** कैसे ** मैं बाहर के दायरे चर का उपयोग कर सकते पता लगा सकते हैं" के लिए रवाना स्पष्ट रूप से कर रहे हैं। मुझे नहीं लगता कि प्रश्नकर्ता एक noob ... –