दिलचस्प पोस्ट
दर्ज किए गए संपादन टेक्स्ट में पाठ साफ़ करें कॉरलाइनिस को कॉल करने का अधिक संगठित तरीका? एनिमेशन के माध्यम से एक गतिविधि में स्वैप टुकड़ा कोर डाटा और कोर स्थान फ़ाइल पर एक्सप्लोरर को खोलें जावामेल एक्सचेंज प्रमाणीकरण मैं मूल तत्व जानने के बिना एक nth बच्चे कैसे चुन सकता हूँ? जावास्क्रिप्ट का `window.resizeTo` काम नहीं कर रहा है चार्ट.जेएस में प्रत्येक टुकड़ा के पाई चार्ट डेटा वैल्यू कैसे प्रदर्शित करें चयनित सूची बॉक्स आइटम के लिए पृष्ठभूमि का रंग बदलें क्या std :: vector मेमोरी एक स्पष्ट पर मुक्त है? अंगुलुज में इकाई परीक्षण का वादा-आधारित कोड जावास्क्रिप्ट document.cookie हमेशा खाली स्ट्रिंग जावा में ऑब्जेक्ट ऑब्जेक्ट्स को कैसे क्वेरी करते हैं (मानदंड / एसक्यूएल-जैसी)? एचटीएमएल इनपुट टाइप = फाइल, फॉर्म जमा करने से पहले छवि प्राप्त करें

आलोचना मेरे गैर-घुसपैठ ढेर डीबगर

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

ढेर डीबगर अब निम्न प्रकार की त्रुटियों का पता लगाता है:

  1. मेमोरी लीक (अब अधिक वर्बोज़ डीबगिंग आउटपुट के साथ)
  2. अवैध संकेत हटाने के लिए पास (जो भी डबल हटाए का ख्याल रखता है)
  3. मिटाने का गलत रूप (सरणी बनाम गैर-सरणी)
  4. बफर ओवरफ्लो
  5. बफर अंडरफ्लो

अग्रिम में चर्चा करने और धन्यवाद करने के लिए स्वतंत्र महसूस करें!

#include <cstdio> #include <cstdlib> #include <cstring> #include <new> namespace { // I don't want to #include <algorithm> for a single function template :) template <typename T> void my_swap(T& x, T& y) { T z(x); x = y; y = z; } typedef unsigned char byte; const byte CANARY[] = {0x5A, 0xFE, 0x6A, 0x8D, 0x5A, 0xFE, 0x6A, 0x8D, 0x5A, 0xFE, 0x6A, 0x8D, 0x5A, 0xFE, 0x6A, 0x8D}; bool canary_dead(const byte* cage) { bool dead = memcmp(cage, CANARY, sizeof CANARY); if (dead) { for (size_t i = 0; i < sizeof CANARY; ++i) { byte b = cage[i]; printf(b == CANARY[i] ? "__ " : "%2X ", b); } putchar('\n'); } return dead; } enum kind_of_memory {AVAILABLE, TOMBSTONE, NON_ARRAY_MEMORY, ARRAY_MEMORY}; const char* kind_string[] = {0, 0, "non-array memory", " array memory"}; struct metadata { byte* address; size_t size; kind_of_memory kind; bool in_use() const { return kind & 2; } void print() const { printf("%s at %p (%d bytes)\n", kind_string[kind], address, size); } bool must_keep_searching_for(void* address) { return kind == TOMBSTONE || (in_use() && address != this->address); } bool canaries_alive() const { bool alive = true; if (canary_dead(address - sizeof CANARY)) { printf("ERROR: buffer underflow at %p\n", address); alive = false; } if (canary_dead(address + size)) { printf("ERROR: buffer overflow at %p\n", address); alive = false; } return alive; } }; const size_t MINIMUM_CAPACITY = 11; class hashtable { metadata* data; size_t used; size_t capacity; size_t tombstones; public: size_t size() const { return used - tombstones; } void print() const { for (size_t i = 0; i < capacity; ++i) { if (data[i].in_use()) { printf(":( leaked "); data[i].print(); } } } hashtable() { used = 0; capacity = MINIMUM_CAPACITY; data = static_cast<metadata*>(calloc(capacity, sizeof(metadata))); tombstones = 0; } ~hashtable() { free(data); } hashtable(const hashtable& that) { used = 0; capacity = 3 * that.size() | 1; if (capacity < MINIMUM_CAPACITY) capacity = MINIMUM_CAPACITY; data = static_cast<metadata*>(calloc(capacity, sizeof(metadata))); tombstones = 0; for (size_t i = 0; i < that.capacity; ++i) { if (that.data[i].in_use()) { insert_unsafe(that.data[i]); } } } hashtable& operator=(hashtable copy) { swap(copy); return *this; } void swap(hashtable& that) { my_swap(data, that.data); my_swap(used, that.used); my_swap(capacity, that.capacity); my_swap(tombstones, that.tombstones); } void insert_unsafe(const metadata& x) { *find(x.address) = x; ++used; } void insert(const metadata& x) { if (2 * used >= capacity) { hashtable copy(*this); swap(copy); } insert_unsafe(x); } metadata* find(void* address) { size_t index = reinterpret_cast<size_t>(address) % capacity; while (data[index].must_keep_searching_for(address)) { ++index; if (index == capacity) index = 0; } return &data[index]; } void erase(metadata* it) { it->kind = TOMBSTONE; ++tombstones; } } the_hashset; struct heap_debugger { heap_debugger() { puts("heap debugger started"); } ~heap_debugger() { the_hashset.print(); puts("heap debugger shutting down"); } } the_heap_debugger; void* allocate(size_t size, kind_of_memory kind) throw (std::bad_alloc) { byte* raw = static_cast<byte*>(malloc(size + 2 * sizeof CANARY)); if (raw == 0) throw std::bad_alloc(); memcpy(raw, CANARY, sizeof CANARY); byte* payload = raw + sizeof CANARY; memcpy(payload + size, CANARY, sizeof CANARY); metadata md = {payload, size, kind}; the_hashset.insert(md); printf("allocated "); md.print(); return payload; } void release(void* payload, kind_of_memory kind) throw () { if (payload == 0) return; metadata* p = the_hashset.find(payload); if (!p->in_use()) { printf("ERROR: no dynamic memory at %p\n", payload); } else if (p->kind != kind) { printf("ERROR:wrong form of delete at %p\n", payload); } else if (p->canaries_alive()) { printf("releasing "); p->print(); free(static_cast<byte*>(payload) - sizeof CANARY); the_hashset.erase(p); } } } void* operator new(size_t size) throw (std::bad_alloc) { return allocate(size, NON_ARRAY_MEMORY); } void* operator new[](size_t size) throw (std::bad_alloc) { return allocate(size, ARRAY_MEMORY); } void operator delete(void* payload) throw () { release(payload, NON_ARRAY_MEMORY); } void operator delete[](void* payload) throw () { release(payload, ARRAY_MEMORY); } int main() { int* p = new int[1]; delete p; // wrong form of delete delete[] p; // ok delete p; // no dynamic memory (double delete) p = new int[1]; p[-1] = 0xcafebabe; p[+1] = 0x12345678; delete[] p; // underflow and overflow prevent release // p is not released, hence leak } 

Solutions Collecting From Web of "आलोचना मेरे गैर-घुसपैठ ढेर डीबगर"

वाकई बहूत बढिया। आपके कैनरीज़ वास्तव में अतिप्रवाह / अंडरफ्लो के कुछ वास्तविक मामलों को प्रकट कर सकते हैं (हालांकि उन सभी को नहीं, जैसा कि मथिएू ने बताया है)।

और क्या। आप बहु-थ्रेडेड एप्लिकेशन के साथ कुछ समस्याएं चल सकते हैं शायद समवर्ती पहुंच से हैशटेबल की सुरक्षा करें?

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

यदि आप विभिन्न धागे की तुलना करना चाहते हैं, तो कम से कम Pthreads के साथ आप उन्हें pthread_self () के साथ पहचान सकते हैं। यह ढेर डीबगर काफी उपयोगी विश्लेषण उपकरण बन सकता है

क्या आप एक बहुत ही कमजोर मॉलोक का प्रयोग कर रहे हैं जो पहले से ही इस तरह के सामान में निर्मित नहीं है? क्योंकि अगर ऐसा है, तो आप छोटे लाभ के लिए ओवरहेड को दोहरी कर रहे हैं। इसके अलावा, इस प्रकार की व्यवस्था वास्तव में छोटे ऑब्जेक्ट आवंटन करते समय परेशान होती है या उनके साथ अप्रभावी होती है क्योंकि लोग 1 एलोक और खुद को स्मृति का प्रबंधन करते हैं।

जहां तक ​​कोड का संबंध है, ऐसा लगता है कि यह आपके द्वारा किया जाने वाला काम करेगा और यह अच्छी तरह से डिज़ाइन और पढ़ना आसान है। लेकिन, यदि आप इसे करने की परेशानी से गुजरते हैं, तो प्रबंधित कंटेनर / पॉइंटर्स / ऑपरेटर [] चीजों के जरिए स्रोत पर अपने बफर को / नीचे प्रवाह में न पकड़ें। इस तरह, आप मुफ्त में खोजने के बजाय विफलता के स्थान पर डिबग कर सकते हैं जो कुछ बुराई हुई है।

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

मैं अंडरफ्लो / ओवरफ्लो का पता लगाने के बारे में सोचता हूं

मेरा मतलब है, अगर मेरे पास 10 तत्व एरेज़ हैं, तो ऐसा लगता है कि मुझे पता होगा कि मैं -1 और 10 लिखता हूं, लेकिन अगर मैं 20 पर लिखूं तो क्या होगा? अंडरफ्लो या अतिप्रवाह जरूरी नहीं कि बफर ओवररन के भाग के रूप में किया जाता है (निकटवर्ती)।

इसके अलावा, ब्लॉक के रिलीज को रोकने की क्या बात है? यह ब्लॉक (अपेक्षाकृत) ठीक है, यह पड़ोसियों आपके पास है (दुर्भाग्य से) दूषित।

वैसे भी, यह मेरे लिए बहुत अच्छा लगता है, हालांकि मुझे शायद प्रति फ़ंक्शन प्रति एक से अधिक रिटर्न मिलेगा क्योंकि एकल एक्ज़िट में कोई बात नहीं है। आपको सी ++ के एक सी प्रोग्रामर से ज्यादा लगता है 🙂