2009-02-24 11 views
19

मैं अपने प्रोग्राम में थोड़ा मेमोरी लीक खोजक बना रहा हूं, लेकिन नया ओवरलोडिंग और हटाए जाने का मेरा तरीका (और नया [] और हटाएं []) कुछ भी नहीं प्रतीत होता है।नया ओवरलोडिंग/हटाएं

void* operator new (unsigned int size, const char* filename, int line) 
{ 
    void* ptr = new void[size]; 
    memleakfinder.AddTrack(ptr,size,filename,line); 
    return ptr; 
} 

जिस तरह से मैंने ओवरलोड किया new ऊपर कोड स्निपेट में दिखाया गया है। मुझे लगता है कि यह ऑपरेटर के साथ शून्य है * लेकिन मुझे नहीं पता कि इसके बारे में क्या करना है।

+6

"कुछ भी नहीं लगता है": आपका क्या मतलब है? आपने ऑपरेटर को अधिभारित किया है, लेकिन आपने डिफ़ॉल्ट ऑपरेटर को * ओवरराइड नहीं किया है, इसलिए "नया एक्स" डिफ़ॉल्ट रूप से नया कॉल करता है जबकि "नया (फ़ाइल नाम, रेखा) x" आपके अधिभारित संस्करण को कॉल करता है। –

उत्तर

11
void* ptr = new void[size]; 

ऐसा नहीं कर सकता। इसे ठीक करो।

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

void * operator new(size_t size) _THROW1(_STD bad_alloc) 
{  // try to allocate size bytes 
    void *p; 
    while ((p = malloc(size)) == 0) 
    if (_callnewh(size) == 0) 
    {  // report no memory 
     static const std::bad_alloc nomem; 
     _RAISE(nomem); 
    } 

    return (p); 
} 
+3

दरअसल, मेरे पास एक बार ऐसा करने का एक अच्छा कारण था।हमारे पास एक कंपाइलर "मुद्दा" था जहां यह डीएलएल सीमाओं में एक असुरक्षित तरीके से ढेर का उपयोग कर रहा था। फिक्स "नया" का एक कस्टम संस्करण बनाना था जो एक विशिष्ट नामित ढेर का उपयोग करता था। –

+0

आपने एक बग क्यों नहीं दर्ज की और इसके बजाय आग से खेलना चुना? – dirkgently

+0

हमने किया। प्रतिक्रिया जो हमने वापस प्राप्त की थी, "डीएलएल हमारी प्रणाली में बहुत अच्छी तरह से क्रॉस-प्रोसेस नहीं करते हैं" के साथ कुछ था। हम अंततः उनका उपयोग छोड़ दिया, लेकिन अल्प अवधि में इस समस्या को हल किया। –

4

क्या आप ओवरलोडेड ऑपरेटर को सही तरीके से आमंत्रित कर रहे हैं, यानी, इसे अतिरिक्त पैरामीटर पास कर रहे हैं?

4

समस्या दो तर्क है कि आप अतिभारित नए ऑपरेटर को जोड़ा गया है के साथ निर्भर करता है:

यहाँ VS2005 new.cpp से new ऑपरेटर के एक आसुत संस्करण है। किसी भी तरीके से फ़ाइल नाम और लाइन वैश्विक बनाने का प्रयास करें (या सदस्य चर, यदि आप नए अधिभारित कर रहे हैं और एक वर्ग के लिए हटाएं)। यह बेहतर काम करना चाहिए।

12

मुझे लगता है कि यहां समस्या यह है कि आपकी नई पैरामीटर प्रोफ़ाइल मानक ऑपरेटर के नए से मेल नहीं खाती है, ताकि कोई छुपा नहीं जा रहा हो (और इस प्रकार अभी भी उपयोग किया जा रहा है)।

के लिए आपका पैरामीटर प्रोफाइल नए और इस तरह देखने के लिए की जरूरत को हटा दें:

void* operator new(size_t); 
void operator delete(void*, size_t); 
44

शायद तुम पूर्वप्रक्रमक जादू का एक छोटा सा के साथ आप क्या चाहते हैं कर सकते हैं:

#include <iostream> 

using namespace std; 

void* operator new (size_t size, const char* filename, int line) { 
    void* ptr = new char[size]; 
    cout << "size = " << size << " filename = " << filename << " line = " << line << endl; 
    return ptr; 
} 

#define new new(__FILE__, __LINE__) 

int main() { 
    int* x = new int; 
} 
+12

यह कमाल है। –

+2

क्या यह 'हस्ताक्षरित int' के बजाय 'size_t' होना चाहिए? मुझे विश्वास है कि कुछ प्लेटफार्मों पर इन प्रकार के बराबर नहीं हैं। – iggy

+0

क्यों 'शून्य * ऑपरेटर नया (आकार_टी आकार, कॉन्स char * फ़ाइल नाम, int लाइन)' पहला तर्क 'size_t' है? अगर मैं 'डिलीट' ऑपरेटर को ओवरराइड करना चाहता हूं, तो मुझे क्या लिखना चाहिए? – naive231

121

उत्तर:

कभी भी नए स्तर को ओवरलोड करने का प्रयास न करें/वैश्विक स्तर पर

जब भी कोई सी ++ की कम आम सुविधा का उपयोग करने का प्रयास करता है, तो ऐसा कोई काम करता है जैसे इसे कभी नहीं किया जाना चाहिए?

यह हर समय किया जाता है, यह काफी आम है, और मैंने कंपनी के लिए काम नहीं किया है जो ऐसा नहीं करता है।

वैश्विक स्तर पर नई अतिभारित और हटाने इत्यादि

उनके सही मन में

कोई भी कोड के कई लाख लाइनों के साथ एक कार्यक्रम के माध्यम से जाना है, और एक जोड़ने जा रहा है पर नज़र रखने के स्मृति, स्मृति कीड़े, बफर लगने में बहुत मददगार रहे हैं नया और प्रत्येक वर्ग को सदस्य हटा दें। यह सिर्फ बेवकूफ है।

+1

* अधिभार * के बजाय नए/हटाए जाने के * ओवरराइड * की आवश्यकता होगी। मुझे हाल ही में ऐसा करना पड़ा (और कारण मैं इस प्रश्न में आया) एक आरटीओएस का उपयोग कर एम्बेडेड सिस्टम पर। हालांकि आरटीओएस ने मॉलोक/फ्री के लिए थ्रेड-सेफ रैपर प्रदान किए हैं, एप्लिकेशन को सी ++ में नए/डिलीट के साथ लिखा गया था। थ्रेड-सुरक्षित मॉलोक/डिलीट के तेह उपयोग को मजबूर करने के लिए, वैश्विक स्तर पर नया/हटाएं ओवरराइड करना आवश्यक था। हालांकि नया [], हटाएं [] और नया (std :: nothrow) और हटाएं (std :: nothrow) को भी विचार करने की आवश्यकता है। – Clifford

+0

सच्चाई यह है कि नए को अमूर्त करना और मैक्रो से दूर होना बेहतर है। नया(), हटाएं()। यह आपको अतिरिक्त कार्यों को करने के लिए बाध्य करेगा जैसे स्टैक फ्रेम खींचें, एक फ़ाइल और लाइन # लॉग करें, एक पूर्वनिर्धारित ढेर से आवंटित करें और इसे अस्तित्व में नया स्थान दें। ओवरलोडिंग में लचीलापन की पूरी श्रृंखला नहीं है जिसे पूर्ण अमूर्तता के माध्यम से हासिल किया जा सकता है। – Dan

+1

इसके अलावा, अपना स्वयं का ओएस लिखना एक अच्छा एप्लीकेशन है। – imallett

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