यदि स्वचालित उपकरण (जैसे इलेक्ट्रिक बाड़ या वालग्रिंड) चाल नहीं करते हैं, और अपने कोड पर ध्यान से देखकर यह पता लगाने के लिए कि यह गलत हो गया है, यह मदद नहीं करता है, और विभिन्न परिचालनों को अक्षम/सक्षम करने में सक्षम नहीं है (जब तक आप ढेर-भ्रष्टाचार की उपस्थिति और पहले से निष्पादित नहीं किए गए कार्यों के बीच एक सहसंबंध प्राप्त करते हैं) इसे संकीर्ण करने के लिए काम नहीं लगता है, आप हमेशा इस तकनीक को आजमा सकते हैं, जो बाद में भ्रष्टाचार को जल्द से जल्द खोजने का प्रयास करता है
अपने स्वयं के कस्टम बनाएं नया और ऑपरेटरों कि आबंटित स्मृति क्षेत्रों के आस-भ्रष्टाचार स्पष्ट गार्ड क्षेत्रों में कहें, कुछ इस तरह हटा दें::
, इतनी के रूप में यह आसान नीचे स्रोत ट्रैक करने के लिए बनाने के लिए 210
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <new>
// make this however big you feel is "big enough" so that corrupted bytes will be seen in the guard bands
static int GUARD_BAND_SIZE_BYTES = 64;
static void * MyCustomAlloc(size_t userNumBytes)
{
// We'll allocate space for a guard-band, then space to store the user's allocation-size-value,
// then space for the user's actual data bytes, then finally space for a second guard-band at the end.
char * buf = (char *) malloc(GUARD_BAND_SIZE_BYTES+sizeof(userNumBytes)+userNumBytes+GUARD_BAND_SIZE_BYTES);
if (buf)
{
char * w = buf;
memset(w, 'B', GUARD_BAND_SIZE_BYTES); w += GUARD_BAND_SIZE_BYTES;
memcpy(w, &userNumBytes, sizeof(userNumBytes)); w += sizeof(userNumBytes);
char * userRetVal = w; w += userNumBytes;
memset(w, 'E', GUARD_BAND_SIZE_BYTES); w += GUARD_BAND_SIZE_BYTES;
return userRetVal;
}
else throw std::bad_alloc();
}
static void MyCustomDelete(void * p)
{
if (p == NULL) return; // since delete NULL is a safe no-op
// Convert the user's pointer back to a pointer to the top of our header bytes
char * internalCP = ((char *) p)-(GUARD_BAND_SIZE_BYTES+sizeof(size_t));
char * cp = internalCP;
for (int i=0; i<GUARD_BAND_SIZE_BYTES; i++)
{
if (*cp++ != 'B')
{
printf("CORRUPTION DETECTED at BEGIN GUARD BAND POSITION %i of allocation %p\n", i, p);
abort();
}
}
// At this point, (cp) should be pointing to the stored (userNumBytes) field
size_t userNumBytes = *((const size_t *)cp);
cp += sizeof(userNumBytes); // skip past the user's data
cp += userNumBytes;
// At this point, (cp) should be pointing to the second guard band
for (int i=0; i<GUARD_BAND_SIZE_BYTES; i++)
{
if (*cp++ != 'E')
{
printf("CORRUPTION DETECTED at END GUARD BAND POSITION %i of allocation %p\n", i, p);
abort();
}
}
// If we got here, no corruption was detected, so free the memory and carry on
free(internalCP);
}
// override the global C++ new/delete operators to call our
// instrumented functions rather than their normal behavior
void * operator new(size_t s) throw(std::bad_alloc) {return MyCustomAlloc(s);}
void * operator new[](size_t s) throw(std::bad_alloc) {return MyCustomAlloc(s);}
void operator delete(void * p) throw() {MyCustomDelete(p);}
void operator delete[](void * p) throw() {MyCustomDelete(p);}
... उपरोक्त आप इलेक्ट्रिक-बाड़ शैली की कार्यक्षमता प्राप्त करने के लिए पर्याप्त होंगे, यदि कुछ भी किसी भी नई/हटाए गए स्मृति की शुरुआत या अंत में दो 64-बाइट "गार्ड बैंड" में से किसी एक में लिखता है - आवंटन, जब आवंटन हटा दिया जाता है, MyCustomDelete() भ्रष्टाचार को नोटिस करेगा और कार्यक्रम को दुर्घटनाग्रस्त करेगा।
यदि यह पर्याप्त नहीं है (उदाहरण के लिए जब तक विलोपन होता है, भ्रष्टाचार के बाद से इतना कुछ हुआ है कि भ्रष्टाचार के कारण क्या कहना मुश्किल है), आप आवंटित जोड़कर MyCustomAlloc() को और भी आगे बढ़ा सकते हैं आवंटन की एक सिंगलटन/वैश्विक दोगुनी-लिंक्ड सूची में बफर करें, और MyCustomDelete() को उसी सूची से हटा दें (यदि आपका प्रोग्राम बहुप्रचारित है तो इन परिचालनों को क्रमबद्ध करना सुनिश्चित करें!)। ऐसा करने का लाभ यह है कि आप फिर एक और फ़ंक्शन जोड़ सकते हैं उदा। CheckForHeapCorruption() जो उस लिंक की गई सूची पर फिर से शुरू होगा और लिंक की गई सूची में प्रत्येक आवंटन के गार्ड-बैंड की जांच करेगा, और रिपोर्ट करें कि उनमें से कोई भी दूषित हो गया है। फिर आप अपने पूरे कोड में CheckForHeapCorruption() पर कॉल छिड़का सकते हैं, ताकि जब भ्रष्टाचार ढेर हो जाए तो यह कुछ समय बाद चेकफोरहेप क्रॉन्शन() को अगली कॉल पर पता लगाया जाएगा। आखिरकार आप पाएंगे कि चेकफोरहेप कन्फ्रेश() को उड़ान रंगों से गुजरने के लिए एक कॉल, और उसके बाद चेकफोरहेपकॉर्प() के लिए अगली कॉल, कुछ ही पंक्तियों बाद भ्रष्टाचार का पता चला, जिस बिंदु पर आप जानते हैं कि भ्रष्टाचार के कारण जो भी कोड निष्पादित किया गया था CheckForHeapCorruption() पर दो कॉल, और फिर आप उस विशेष कोड का अध्ययन कर सकते हैं कि यह गलत तरीके से क्या कर रहा है, और/या उस कोड में चेकफोरहेप क्रॉन्शन() को और कॉल जोड़ना आवश्यक है।
बग स्पष्ट होने तक दोहराएं। सौभाग्य!
'स्मृति' में '256 + 1' क्यों, जब आपने केवल' 256' बाइट आवंटित किए हैं? –
आपके बड़े आवेदन में, आप कैसे जानते थे कि ढेर दूषित हो गया था? आपको किस टूल ने सूचित किया? – PaulMcKenzie
@ टी.जेड। भ्रष्टाचार के प्रकार का प्रदर्शन करने के लिए ... – StoryTeller