2010-08-13 23 views
19

मेरा कुछ कोड अभी भी new के बजाय malloc का उपयोग करता है। इसका कारण यह है कि मुझे new का उपयोग करने से डर है क्योंकि यह NULL लौटने के बजाय अपवाद फेंकता है, जिसे मैं आसानी से देख सकता हूं। try{}catch(){} में प्रत्येक कॉल को new पर लपेटना भी अच्छा नहीं दिखता है। जबकि malloc का उपयोग करते समय मैं केवल if (!new_mem) { /* handle error */ } कर सकता हूं।क्या सी ++ स्मार्ट पॉइंटर्स का उपयोग सी के मॉलोक के साथ करना संभव है?

इसलिए मेरे पास एक प्रश्न है। क्या मैं malloc के साथ स्मार्ट पॉइंटर्स का उपयोग कर सकता हूं?

कुछ की तरह:

SmartPointer<Type> smarty = malloc(sizeof(Type)); 

कुछ इस तरह।

क्या यह संभव है?

धन्यवाद, बोडा साइडो।

+2

यदि आप अब अपवाद फेंकना चाहते हैं और केवल वापस लौटाना चाहते हैं तो आप इसका उपयोग कर सकते हैं: टाइप * bla = new (std :: nothrow) टाइप() ;. मुझे लगता है कि बाद में malloc की तुलना में std :: nothrow का उपयोग करना बेहतर है क्योंकि बाद में निर्माता को कॉल नहीं किया जाता है। –

+1

स्मृति प्राप्त करने के लिए क्षतिपूर्ति करने के लिए त्रुटि प्रबंधन कोड में आप क्या करने जा रहे हैं? आम तौर पर परीक्षण तब होता है जब आवंटन काम करता है तो काम करता है। यदि यह एक त्रुटि कोड से बाहर निकलने में विफल रहा है (जो स्टैक बैक अप बैक अप कंट्रोल है)। –

उत्तर

31

, आप एक कस्टम Deleter निर्दिष्ट कर सकते हैं। उदाहरण के लिए,

struct free_delete 
{ 
    void operator()(void* x) { free(x); } 
}; 

यह बहुत तरह shared_ptr के साथ प्रयोग किया जा सकता है:

std::shared_ptr<int> sp((int*)malloc(sizeof(int)), free_delete()); 

आप unique_ptr का उपयोग कर रहे हैं, तो Deleter unique_ptr के प्रकार का एक हिस्सा है, इसलिए Deleter होने की जरूरत है

std::unique_ptr<int, free_delete> up((int*)malloc(sizeof(int))); 

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

+0

आप सीधे 'फ्री' भी पास कर सकते हैं: 'ऑटो myPointer = std :: unique_ptr (..., मुफ्त) ' –

+2

@ पैट्रिक चिल्टन नोट करें कि यदि आप ऐसा करते हैं, तो आपका' unique_ptr' दो गुना बड़ा होगा। –

1

यह क्या SmartPointer विनाश पर करता है पर निर्भर करता है। यदि आप free को एक डीलोकेटर के रूप में निर्दिष्ट कर सकते हैं, तो यह काम कर सकता है। उदाहरण के लिए, boost :: shared_ptr आपको एक डिलीटर निर्दिष्ट करने की अनुमति देता है।

मैं इस चाहने के लिए अपने कारण करने के लिए पर्याप्त ध्यान नहीं दिया। मैं अन्य उत्तरों से सहमत हूं कि नोट्रो new का उपयोग करना एक बेहतर विचार है।

1

यह स्मार्ट संकेत (आप हालांकि, सूचक प्रकार लक्षित करते हैं और कस्टम deallocator प्रदान करने के लिए दिया गया मान कास्ट करने के लिए है) के साथ malloc उपयोग करना संभव है। लेकिन बेहतर विकल्प nothrownew ऑपरेटर का संस्करण उपयोग करना है।

http://www.cplusplus.com/reference/std/new/nothrow/

9

आप नए ऑपरेटर, जो बल्कि कि एक अपवाद फेंक NULL वापस आ जाएगी साथ कीवर्ड nothrow उपयोग कर सकते हैं। विवरण नीचे दिए गए लिंक को देखने के लिए: यदि आप shared_ptr या unique_ptr उपयोग कर रहे हैं http://www.cplusplus.com/reference/std/new/nothrow/

+1

'नोट्रो' का उपयोग एक सामान्य अभ्यास का उपयोग कर रहा है? (क्योंकि मैंने वास्तव में वास्तविक अभ्यास में व्यक्तिगत रूप से ध्यान देने का उपयोग नहीं किया है।) – bodacydo

+7

जब आप इसे अपवाद फेंकना नहीं चाहते हैं तो यह 'नया' उपयोग करने का सबसे आम तरीका है। लेकिन नहीं, * अपवाद हैंडलिंग के साथ 'नया' और काम * का उपयोग करना अधिक आम है। यदि आवंटन विफल रहता है, तो आप आमतौर पर इसके बारे में अधिक कुछ नहीं कर सकते हैं, इसलिए अपवाद प्रचार को छोड़कर शानदार तरीके से बाहर निकलने का एक बहुत साफ तरीका है। – jalf

1

/* handle error */ में कौन सा कोड चला जाता है? क्या कोई ऐसी चीज है जिसे आप वास्तव में स्मृति से बाहर कर सकते हैं? मैं सिर्फ कॉल स्टैक (कोर डंप) के साथ समाप्त होने देता हूं, इसलिए मेरे पास कम से कम एक संभावित स्थान है जो समस्याएं पैदा कर सकता है।

सी ++ कक्षाओं और वस्तुओं के लिए स्मृति आवंटित करने के लिए malloc का उपयोग करना एक अच्छा विचार नहीं है क्योंकि यह सुनिश्चित नहीं करेगा कि रचनाकारों को बुलाया जा सकता है, संभवतः आपको अनियमित वर्गों के साथ छोड़ दिया जा सकता है जो उनके पास आभासी तरीकों से भी क्रैश हो सकते हैं।

बस new और delete का उपयोग करें और अपवाद को पकड़ने के बारे में चिंता न करें, स्मृति से बाहर निकलने के बाद एक असाधारण मामला है और आवेदन के सामान्य रनों में नहीं होना चाहिए।

+0

ऐसी कुछ स्थितियां हैं जिनमें आप त्रुटि को प्रबंधित कर सकते हैं। उदाहरण के लिए, स्मृति-लालच संख्यात्मक गणना (उदा। सिमुलेशन) आसानी से कमजोर मशीनों पर स्मृति से बाहर हो सकती है, लेकिन इस मामले में आप तुरंत रुक सकते हैं और क्रैश होने की बजाय त्रुटि प्रदर्शित कर सकते हैं। – Yury

1

nothrow का उपयोग करें।

Nothrow निरंतर

यह लगातार मूल्य नए ऑपरेटर और ऑपरेटर के लिए एक तर्क के रूप में प्रयोग किया जाता है नई [] संकेत मिलता है कि इन कार्यों विफलता पर एक अपवाद फेंक नहीं होगी, लेकिन एक वापसी इसके बजाय शून्य सूचक ।

char* p = new (nothrow) char [1048576]; 
if (p==NULL) cout << "Failed!\n"; 
else { 
    cout << "Success!\n"; 
    delete[] p; 
} 
3

सबसे अच्छा समाधान new (std::nothrow) Type उपयोग करने के लिए है। यह new Type की तरह कार्य करेगा, लेकिन अगर यह विफल हो जाता है तो फेंकने के बजाय शून्य देगा। mallocnew की तरह व्यवहार करने की कोशिश करने से यह बहुत आसान होगा।

तुम सच में malloc उपयोग करना आवश्यक है, तो सही ढंग से निर्माण और वस्तु संहार करने के लिए याद रखें:

void malloc_deleter(Type* object) 
{ 
    object->~Type(); 
    free(object); 
} 

if (void* memory = malloc(sizeof(Type))) 
{ 
    Type* object = new (memory) Type; 
    std::shared_ptr<Type> ptr(object, malloc_deleter); 
    DoStuff(ptr); 
} 
:

void* memory = malloc(sizeof(Type)); 
Type* object = new (memory) Type; 
object->~Type(); 
free(object); // or free(memory) 

आप इसे एक कस्टम Deleter देकर एक कुछ स्मार्ट संकेत के साथ इस का उपयोग कर सकते

लेकिन यह बहुत सरल का उपयोग करते हुए किया जाएगा गैर फेंकने नया:

if (Type* object = new (std::nothrow) Type) 
{   
    std::shared_ptr<Type> ptr(object); 
    DoStuff(ptr); 
} 
+0

मॉलोक का उपयोग करने से आपको रीयलोक का उपयोग करने का अतिरिक्त लाभ होता है: http://stackoverflow.com/a/33706568/1858225 –

1

मेरे पास एक सवाल है।

क्या होता है यदि "टाइप" एक प्रकार है जिसका कन्स्ट्रक्टर फेंक सकता है? उस स्थिति में, किसी को अभी भी कोशिश/पकड़ ब्लॉक में अपवादों को संभालने की आवश्यकता है।

तो अपवाद आधारित दृष्टिकोण को त्यागना एक अच्छा विचार है?

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

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