क्या पता 0000000C एक विशेष पता है?


32

जब कभी-कभी प्रोग्रामिंग टूट जाती है। आपने एक गलती की और आपका कार्यक्रम एक गलत पते से पढ़ने की कोशिश करता है।

एक बात जो मेरे सामने है कि अक्सर वे अपवाद इस प्रकार हैं:

Access violation at address 012D37BC in module 'myprog.exe'. Read of address 0000000C.

अब मुझे बहुत सारे त्रुटि लॉग दिखाई दे रहे हैं और जो मेरे लिए खड़ा है वह है: 0000000C। क्या यह "विशेष" पता है? मुझे खराब रीड्स के साथ अन्य एक्सेस उल्लंघन दिखाई देते हैं लेकिन पते बस यादृच्छिक लगते हैं, लेकिन यह पूरी तरह से अलग स्थितियों में वापस आता रहता है।


1
मैं भी देखा है कि 0000000Cहै जिस तरह से अधिक आम 00000008है, लेकिन जवाब में से कोई भी पता लगता है कि सभी पर: /
राँभना बतख

2
शायद कि System.Runtime.CompilerServices.RuntimeHelpers.OffsetToStringDataहै 12=0x0Cक्यों यह भरपाई ज्यादा आम है एक कारण है।
मार्क हर्ड

1
@MarkHurd यह डरावना है। क्या आप वास्तव में सोचते हैं कि बहुत सारे अप्रबंधित अनुप्रयोग हैं जो उद्देश्य से .NET स्ट्रिंग्स को पढ़ते / लिखते हैं कि यह एक्सेस उल्लंघनों का एक प्रमुख स्रोत होगा?
लुआं

जवाबों:


57

00000000एक विशेष पता (अशक्त सूचक) है। 0000000Cजब आप 12 से अशक्त सूचक को ऑफ़सेट जोड़ते हैं, तो सबसे अधिक संभावना होती है क्योंकि किसी ने किसी zसंरचना के सदस्य को सूचक के माध्यम से नीचे की तरह प्राप्त करने का प्रयास किया था जो वास्तव में अशक्त था।

struct Foo {
    int w, x, y; // or anything else that takes 12 bytes including padding
    // such as: uint64_t w; char x;
    // or: void *w; char padding[8];
    // all assuming an ordinary 32 bit x86 system
    int z;
}

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

3
मैंने यह सवाल इसलिए पूछा क्योंकि 0000000C अन्य विज्ञापनों की तुलना में इतनी बार वापस आता है। क्यों ऑफसेट 12 एक परिमाण अधिक आम है तो ऑफसेट 4, 8 या 16?
Pieter B

5
आगे की जांच के बाद यह उत्तर पूरी तरह से सही है। मेरे स्रोत में वर्गों की "टैग" संपत्ति का बड़े पैमाने पर उपयोग किया जाता है (या तो मुझे अच्छा या बुरा मुझे इससे निपटना है।) मेरे मामले में टैग संपत्ति एक निम्न स्तर के आधार वर्ग का हिस्सा है और यह हमेशा उस ऑफसेट पर बनाई गई है।
पीटेर बी

1
बहुत बढ़िया बिंदु। शायद अशक्त सूचक मामले को कवर किया गया था, लेकिन अशक्त सूचक ++ केवल एक सामान्य (और इस मामले में अमान्य) पता है, इस प्रकार यह केवल इसे एक्सेस करने पर विफल रहता है।
नील

8
@Leushenko हाँ, स्मृति संरक्षण आमतौर पर पूरे पृष्ठों पर काम करता है, और भले ही यह केवल 0 को पकड़ने के लिए संभव था, यह निम्नलिखित पते की सुरक्षा करना भी बेहतर है क्योंकि वे एक अशक्त सूचक के साथ सूचक अंकगणित होने की संभावना है क्योंकि (जैसा कि होता है) ओपी का मामला)।

11

विंडोज में यह भिन्नता गैर कानूनी है पूरे पहली और आखिरी पेज , दूसरे शब्दों में प्रक्रिया स्मृति के प्रथम या अंतिम 64 KiB (पर्वतमाला 0x00000000के लिए 0x0000ffffऔर 0xffff0000करने के लिए 0xffffffffएक 32-बिट अनुप्रयोग में)।

यह एक अशक्त सूचक या अनुक्रमणिका के अपरिभाषित व्यवहार को एक अशक्त सरणी में फंसाने के लिए है। और पृष्ठ का आकार 64 KiB है, इसलिए Windows को पहले या अंतिम पृष्ठ को एक मान्य श्रेणी असाइन करने से रोकना है।

यह किसी भी मूल्य (वैध पते सहित) हो सकता है कि अनधिकृत संकेत के खिलाफ गार्ड नहीं होगा।


7
विंडोज वास्तव में ऐसा नहीं कर सकता। पृष्ठ तालिका एक संरचना है जिसे x86 द्वारा परिभाषित और आवश्यक किया गया है, और छोटे पृष्ठ 4KB पर तय किए गए हैं। यह पत्थर में स्थापित है (अधिक सटीक, सिलिकॉन में)। 64KB शायद सुविधा के लिए है।
एल्डरबग

12
मैं इस मामले में ६५ kB के बजाय ६४ KiB लिखूंगा, क्योंकि पॉवर ऑफ़-टू साइज़ प्रासंगिक है।
कोडइन्चोस

4
64KB रेंज NT के Aplha संस्करण से एक बाईं ओर है। और यह पृष्ठ का आकार नहीं है, लेकिन आवंटन की ग्रैन्युलैरिटी है। blogs.msdn.com/b/oldnewthing/archive/2003/10/08/55239.aspx
shf301

3
@CodesInChaos: जबकि अपरकेस "एम", "जी", और "टी" अस्पष्ट हैं, मुझे 10 ^ 3 के लिए "k" और 2 ^ 10 के लिए "K" के उपयोग को कम करने का कोई कारण नहीं दिखता है।
सुपरकैट

2
@MooingDuck वास्तव में हां, यही कारण है कि मैंने छोटे पृष्ठ बनाए हैं। अधिकांश x64 CPU भी 1GiB पृष्ठों का समर्थन करते हैं। जहां तक ​​मुझे पता है, विंडोज हमेशा 4KB पेजों के साथ पेज करता है, जब तक कि विशेष एपीआई के साथ आवंटित नहीं किया जाता है।
एल्डरबग

2

क्यों की 0x0Cतुलना में अधिक सामान्य लगता है 0x08(क्या यह वास्तव में है? मुझे नहीं पता; और किस प्रकार के अनुप्रयोगों में?), यह वर्चुअल विधि तालिका पॉइंटर्स के साथ करना पड़ सकता है। यह वास्तव में एक टिप्पणी के अधिक है (जंगली द्रव्यमान का अनुमान लगाने वाला :), लेकिन यह कुछ हद तक बड़ा है, इसलिए यहां जाता है ... यदि आपको आभासी विधियों के साथ एक वर्ग मिला है, तो इसके अपने क्षेत्रों को स्थानांतरित किया जाएगा 0x04। उदाहरण के लिए, एक वर्ग जो दूसरे आभासी वर्ग से विरासत में मिला है, उसके पास इस तरह का मेमोरी लेआउट हो सकता है:

0x00 - VMT pointer for parent
0x04 - Field 1 in parent
0x08 - VMT pointer for child
0x0C - Field 1 in child

क्या यह एक सामान्य परिदृश्य है, या करीब भी है? मुझे यकीन नहीं है। हालाँकि, ध्यान दें कि 64-बिट अनुप्रयोग में, यह और भी दिलचस्प रूप से 0x0Cमूल्य की ओर स्थानांतरित हो सकता है :

0x00 - VMT parent
0x08 - Field 1 parent
0x0C - VMT child
0x14 - Field 2 child

इसलिए वास्तव में बहुत सारे मामले हैं जहां अनुप्रयोगों में अशक्त-सूचक ऑफसेट में महत्वपूर्ण ओवरलैप हो सकते हैं। यह चाइल्ड क्लास में पहला फील्ड हो सकता है, या इसके वर्चुअल मेथड टेबल पॉइंटर - जब भी आप किसी इंस्टेंस पर किसी वर्चुअल तरीके को कॉल करते हैं, तो यदि आप किसी nullपॉइंटर पर वर्चुअल मेथड को कॉल कर रहे हैं , तो आपको इस पर एक्सेस का उल्लंघन होगा। VMT ऑफसेट। इस विशेष मूल्य की व्यापकता तब कुछ सामान्य एपीआई के साथ कुछ हो सकती है जो एक वर्ग प्रदान करती है जिसमें एक समान विरासत पैटर्न, या अधिक संभावना है, एक विशेष इंटरफ़ेस (कुछ वर्गों के लिए बहुत संभव है, जैसे डायरेक्टएक्स गेम्स)। इस तरह से कुछ सामान्य सामान्य कारणों को ट्रैक करना संभव हो सकता है, लेकिन मैं उन अनुप्रयोगों से छुटकारा पाने की कोशिश करता हूं जो बहुत जल्दी से डेरेफेरिंग करते हैं, इसलिए ...


1
यदि आप टिप्पणियों के माध्यम से देखते हैं, तो आप अनुमान लगाने को काफी कम कर सकते हैं।
डेडुप्लिकेटर

@Deduplicator खैर, मुझे लगता है कि प्रबंधित .NET स्ट्रिंग्स का उपयोग असुरक्षित कोड में मैन्युअल पॉइंटर संचालन डरावना के साथ किया जाता है, और यह सोचा कि यह एक्सेस उल्लंघन का और भी बड़ा कारण होगा। "हाँ, यह पूरी तरह से सुरक्षित मेमोरी है, चिंता मत करो, हमने C # का उपयोग किया है। हम सिर्फ C ++ से मैन्युअल रूप से मेमोरी को संशोधित करते हैं, लेकिन यह C # में सुरक्षित है।"
लुआं
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.