2010-06-02 19 views
9

खोजने के लिए एप्लिकेशन सत्यापनकर्ता का उपयोग कैसे करें मैं मानक उपयोगिताओं का उपयोग कर अपने आवेदन में मेमोरी लीक ढूंढना चाहता हूं। पहले मैंने अपनी खुद की मेमोरी आवंटक का उपयोग किया था, लेकिन अन्य लोगों (हाँ, आप एलियनफ्लिड) ने माइक्रोसॉफ्ट के एप्लिकेशन सत्यापनकर्ता का उपयोग करने का सुझाव दिया, लेकिन मुझे लगता है कि मैं इसे अपने रिसाव की रिपोर्ट नहीं कर सकता।मेमोरी लीक

#include <iostream> 
#include <conio.h> 

class X 
    { 
    public: 
     X::X() : m_value(123) {} 
    private: 
     int m_value; 
    }; 

void main() 
{ 
X *p1 = 0; 
X *p2 = 0; 
X *p3 = 0; 

p1 = new X(); 
p2 = new X(); 
p3 = new X(); 
delete p1; 
delete p3; 
} 

यह परीक्षण स्पष्ट रूप से एक स्मृति रिसाव होता है: p2 new'd है लेकिन उसे हटाया नहीं मैं निम्नलिखित सरल आवेदन किया है।

मैं निम्नलिखित कमांड लाइन का उपयोग कर निष्पादन का निर्माण:

cl /c /EHsc /Zi /Od /MDd test.cpp 
link /debug test.obj 

मैं आवेदन सत्यापनकर्ता डाउनलोड किया गया (4.0.0665) और सभी चेक सक्षम होना चाहिए।

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

सवाल:

  • क्यों नहीं आवेदन सत्यापनकर्ता एक रिसाव रिपोर्ट करता है?
  • या आवेदन सत्यापनकर्ता वास्तव में लीक खोजने का इरादा नहीं है?
  • यदि यह नहीं है कि आवेदन के अंत में स्पष्ट रूप से लीक की रिपोर्ट करने के लिए कौन से अन्य उपकरण उपलब्ध हैं (यानी नियमित स्नैपशॉट नहीं लेना और उन्हें तुलना करना क्योंकि यह 1 जीबी या उससे अधिक के आवेदन में संभव नहीं है), कॉल सहित आवंटन के स्थान के ढेर (ऐसा नहीं सीआरटी के अंत में सरल रिसाव रिपोर्टिंग)

मैं एक सभ्य उपयोगिता नहीं मिल रहा है, तो मैं अभी भी अपने स्वयं के स्मृति प्रबंधक का सहारा लेना पड़ (जो यह करता है पूरी तरह से)।

 
// debug_new.h 
#pragma once 

#include "crtdbg.h" 

#ifdef _DEBUG 
#ifndef DEBUG_NEW 
#define DEBUG_NEW new(_NORMAL_BLOCK, __FILE__, __LINE__) 
#endif 
#endif 

सभी सीपीपी फ़ाइलें:

 
#include "debug_new.h" 

... 

// After all other include lines: 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#endif 

... 

लिखें कार्यक्रम प्रवर्तन कोड में इस बार:

_CrtSetDbgFlag(_CrtSetDbgFlag(_CRTDBG_REPORT_FLAG) | _CRTDBG_LEAK_CHECK_DF); 

में

+0

इस तरह के औजारों में यह समस्या है - हम जो कुछ भी वास्तव में चाहते हैं उसे छोड़कर वे सब कुछ करते हैं ... क्या सीआरटी मेमोरी आपके लिए ठीक है, कोड में आवंटन स्थान सहित, लेकिन कॉल स्टैक के बिना? इस मामले में आपको केवल नए ऑपरेटर को फिर से परिभाषित करने और मेमोरी लीक डंप चालू करने की आवश्यकता है। –

+1

समस्या यह है कि मेरे पास एक पूरी तरह से काम कर रहा है, स्वयं लिखित, स्मृति आवंटक जो काफी तेज़ है, एप्लिकेशन के अंत में कॉल स्टैक, रिपोर्ट लीक (कॉल स्टैक समेत) सहित सभी मेमोरी आवंटन लॉग करता है, बफर ओवरफ़्लो/अंडरफ्लो के लिए चेक करता है। .., लेकिन हर कोई (स्टैक ओवरव्लो पर) इंगित करता है कि आपको अपना खुद का मेमोरी मैनेजर नहीं लिखना चाहिए क्योंकि सीआरटी/विंडोज के मानक एक के लिए पर्याप्त है, और मेमोरी लीक, ओवरराइट्स, ... खोजने के लिए पर्याप्त उपयोगिताएं हैं ... हालांकि, मैं उन्हें काम नहीं कर पा रहा हूं। – Patrick

+1

मुझे यह भी लगता है कि मेमोरी लीक डिटेक्शन आपके स्वयं के मेमोरी आवंटक को लिखने का कारण नहीं है। सीआरटी स्टैक ट्रेस को छोड़कर सब कुछ देता है - यदि आप दिलचस्प हैं, तो मैं आपको कोड पोस्ट कर सकता हूं। –

उत्तर

4

सीआरटी स्मृति का पता लगाने (स्टैक ट्रेस के बिना) लीक एमएफसी, यह सब एमएफसी हेडर में पहले ही लागू हो चुका है। आप केवल सुनिश्चित करने की आवश्यकता है कि हर cpp फ़ाइल इन पंक्तियों में शामिल हैं:

 
#ifdef _DEBUG 
#define new DEBUG_NEW 
#endif 

प्रतिबंध: यह केवल 'नई' मेमोरी लीक, सभी लीक, एक और कार्यों की वजह से, malloc की तरह, पकड़ा नहीं कर रहे हैं फैल जाती है।

.h फ़ाइलों के अंदर कोई आवंटन न करें - उन्हें स्रोत लाइनों के बिना मुद्रित किया जाएगा, क्योंकि DEBUG_NEW को सभी # अंतर्निहित रेखाओं के बाद परिभाषित किया गया है।

+1

यह चाल malloc/free के लिए काम नहीं करती है। सीआरटी की शामिल फाइलों में से एक एमएलएलसी और मुफ़्त (# डिफाई मुफ्त DEBUG_FREE या इस तरह कुछ) के समान कुछ करता है, और इससे कक्षाओं के साथ समस्याएं होती हैं जिनमें एक विधि (जैसे क्यूटी में) होती है। इसके अलावा, यह मेमोरी लीक भी लिखता है, लेकिन कॉल स्टैक्स के बिना, और मुझे वास्तव में कॉल स्टैक की आवश्यकता होती है। – Patrick

1

सबसे आसान समाधान पहले स्थान पर लीक या बफर ओवरफ्लो लिखने के लिए नहीं है - घटना के बाद वास्तव में प्रयास का अपशिष्ट है। अपने कोड में, सालों से मुझे इन क्षेत्रों में शून्य समस्याएं आई हैं। क्यूं कर? Becauase मैं उन तंत्रों का उपयोग करता हूं जो सी ++ उनसे बचने के लिए प्रदान करता है।उदाहरण के लिए:

X *p1 = 0; 
p1 = new X(); 

होना चाहिए:

shared_ptr <X> p1 = new X(); 

और तुम अब p1 लीक के बारे में चिंता। अभी भी बेहतर है, सब पर गतिशील आवंटन का उपयोग नहीं करते:

X x1; 

बफर अतिप्रवाह के लिए, हमेशा std :: स्ट्रिंग की तरह प्रकार जो इनपुट पर बढ़ेगा उपयोग करें, या वे विकसित नहीं यदि संभव हो तो अतिप्रवाह की पहचान करेगा और चेतावनी दी है आप।

मैं मेमोरी लीक से बचने में मेरी कौशल के बारे में दावा कर रहा हूँ नहीं - इस सामग्री वास्तव में काम करता है, और आप अपने कोड की व्यापार तर्क डिबगिंग के और अधिक कठिन कार्य के साथ पर प्राप्त करने के लिए अनुमति देता है।

+3

कई दुर्भाग्यपूर्ण आत्माओं को विरासत कोड (अवांछित बदसूरत सी सामान) से निपटना पड़ता है और सबकुछ फिर से लिखने का जोखिम नहीं उठा सकता है। – Sascha

+1

प्रश्न मेमोरी लीक का पता लगाने के लिए उपकरण मांगता है और उत्तर "घटना के बाद वास्तव में प्रयास की बर्बादी है" के साथ शुरू होता है। आखिरी वक्तव्य के बारे में भी यही कहा जा सकता है "अपने कोड के व्यावसायिक तर्क को डीबग करने के अधिक कठिन कार्य के साथ आगे बढ़ें" - ऐसा कोड क्यों न लिखें जिसे आपके व्यावसायिक तर्क की डीबगिंग की आवश्यकता नहीं है? स्पष्ट रूप से ओपी का उदाहरण लीक कोड के मामले को प्रदर्शित करने के लिए किया गया था और एक प्रश्न reg था। इसे कैसे पहचानें। बेशक कोड को सही करने के लिए यह छोटा है। –

+2

उत्तर वास्तविक दुनिया के लिए पूरी तरह से अनजान है, जहां स्मृति रिसाव मौजूद हैं, और बाहर निकलने की आवश्यकता है। @ सस्चा की तरह, नया कोड लिखना एक बात है और मौजूदा कोड को बनाए रखना एक और बात है। –

1

मुझे एहसास है कि एप्लिकेशन सत्यापनकर्ता विशेष मामलों से बाहर निकलने का मार्ग है और इन्हें लीक के रूप में ध्वजांकित नहीं करता है - आखिरकार, पूरी प्रक्रिया ढेर प्रक्रिया से बाहर निकलने पर मुक्त होती है।

एक और नमूना लिखने का प्रयास करें जहां आप एक ही सूचक को फिर से शुरू करते हैं - मूल रूप से पिछले आवंटन के संदर्भ को खो देते हैं। यह निश्चित रूप से ध्वजांकित किया जाना चाहिए। मुझको परिणाम बता देना।

इसके अलावा, AppVerifier चिह्नित आरओ आदि

+0

बीटीडब्ल्यू, "ग्लोबल फ्लैग" उपयोगिता भी आज़माएं जो विंडोज एसडीके में विंडोज के लिए डिबगिंग टूल्स के साथ आता है। इसमें हेप टैगिंग इत्यादि के लिए विकल्पों का एक गुच्छा है और यह आपको चाहिए जो हो सकता है। – Alienfluid

+1

मैंने पॉइंटर को 0 पर सेट करने का प्रयास किया। एप्लिकेशन सत्यापनकर्ता में कुछ भी रिपोर्ट नहीं की गई। सभी मेमोरी से संबंधित झंडे को सक्षम करने के लिए GFLAGS का उपयोग करने का प्रयास किया। कुछ भी नहीं बताया। ऐसा लगता है कि बाहर निकलने पर मेमोरी लीक प्राप्त करना असंभव है (सीआरटी में बहुत कम रिसाव-रिपोर्टिंग को छोड़कर)। ऐसा लगता है कि मुझे अपने मेमोरी मैनेजर से चिपकना है। – Patrick

4

आवेदन सत्यापनकर्ता केवल DLLs में लीक पकड़ता भी बफर अतिप्रवाह, underflows पकड़ने चाहिए स्थानों ढेर करने के लिए लिख (आप सभी विकल्प सक्षम है)। रिसाव चेकबॉक्स में टूलटिप पढ़ने की कोशिश करें। यही वह कहता है।

0

Visual Leak Detector (v2.2) सीआरटी डीबग लाइब्रेरी से अधिक उपयोगी है क्योंकि यह दिखाएगा कि स्मृति आवंटन के लिए उपयोग किए गए पूर्ण कॉलस्टैक से रिसाव हो गया है।

+0

वीएलडी के साथ काम करना मुश्किल है जब सी ++ सिंगलटन का उपयोग किया जाता है –

1

सॉफ़्टवेयर सत्यापन से मेमोरी वैलिडेटर मेमोरी लीक को पकड़ लेगा, और लीक के आवंटन से पूर्ण कॉलस्टैक दिखाएगा। हालांकि यह एक वाणिज्यिक उत्पाद है, इसकी एक परीक्षण अवधि है इसलिए प्रोग्रामर इसे आजमा सकते हैं और देख सकते हैं कि यह उनके लिए मूल्यवान है या नहीं।

संबंधित मुद्दे