C ++ 20 तक int अपरिभाषित व्यवहार के लिए Malloc का उपयोग कर रहा है


95

मुझे बताया गया था कि निम्न कोड में C ++ 20 तक अपरिभाषित व्यवहार है:

int *p = (int*)malloc(sizeof(int));
*p = 10;

क्या यह सच है?

तर्क यह था कि intवस्तु का जीवनकाल उसके मूल्य ( P0593R6 ) को निर्दिष्ट करने से पहले शुरू नहीं किया जाता है । समस्या को ठीक करने के लिए, प्लेसमेंट newका उपयोग किया जाना चाहिए:

int *p = (int*)malloc(sizeof(int));
new (p) int;
*p = 10;

क्या हमें वास्तव में एक डिफ़ॉल्ट निर्माता को कॉल करना है जो वस्तु के जीवनकाल को शुरू करने के लिए तुच्छ है?

उसी समय, कोड का शुद्ध सी में अपरिभाषित व्यवहार नहीं होता है। लेकिन, क्या होगा अगर मैं intसी कोड में आवंटित करता हूं और सी ++ कोड में इसका उपयोग करता हूं ?

// C source code:
int *alloc_int(void)
{
    int *p = (int*)malloc(sizeof(int));
    *p = 10;
    return p;
}

// C++ source code:
extern "C" int *alloc_int(void);

auto p = alloc_int();
*p = 20;

क्या यह अभी भी अपरिभाषित व्यवहार है?


8
के लिए int? के लिए नहीं std::string? हाँ।
एलजे

8
@Eljay For int, हाँ भी। यह सिर्फ इतना है कि यदि आप ऐसा नहीं करते हैं, तो यह अभ्यास में समस्याएं पैदा नहीं करेगा। के लिए std::string, यह सिर्फ स्पष्ट रूप से समस्याओं का कारण होगा।
बैरी

पूर्व C ++ 20 आप एक प्लेसमेंट नया जोड़ सकते हैं। तब यह अच्छी तरह से बन जाएगा और यह शायद कुछ भी खर्च नहीं करेगा।
फ्रांस्वा एंड्रीक्स

8
C ++ 20 में कौन से नए नियम हैं जो इसे बदलते हैं?
केविन

4
यह नहीं होना चाहिए int *p = (int*)malloc(sizeof(int)); p = new(p) int;? मुझे एक बार एहसास हुआ कि प्लेसमेंट के परिणाम को नया नहीं बताने से घातक प्रभाव पड़ सकते हैं (हालाँकि यह थोड़ा मूर्खतापूर्ण लग सकता है)।
शेफ़

जवाबों:


61

क्या यह सच है?

हाँ। तकनीकी रूप से, इसका कोई हिस्सा नहीं:

int *p = (int*)malloc(sizeof(int));

वास्तव में एक प्रकार की वस्तु का निर्माण होता है int, इसलिए डेरेफ्रेंसिंग pयूबी है क्योंकि वहां कोई वास्तविक intनहीं है।

क्या हमें वास्तव में डिफॉल्ट कंस्ट्रक्टर को कॉल करना है जो ऑब्जेक्ट के जीवन काल को शुरू करने के लिए तुच्छ है?

क्या आपके पास अपरिभाषित व्यवहार से बचने के लिए C ++ ऑब्जेक्ट मॉडल के अनुसार प्री-सी ++ 20 है? हाँ। क्या कोई कंपाइलर वास्तव में ऐसा न करने से आपको नुकसान पहुंचाएगा? यह नही है कि मैं जानता हूँ।

[...] क्या यह अभी भी अपरिभाषित व्यवहार है?

हाँ। प्री-सी ++ 20, आप अभी भी वास्तव में intकहीं भी एक वस्तु नहीं बना रहे हैं इसलिए यह यूबी है।


टिप्पणियाँ विस्तारित चर्चा के लिए नहीं हैं; इस वार्तालाप को बातचीत में स्थानांतरित कर दिया गया है ।
Makyen

इसके लिए UB न होने के लिए समयसीमा- cpp.github.io/cppwp/n3337/basic.life#1.1 में भाषा क्यों नहीं है ? आखिरकार, intउदाहरण के लिए उचित आकार और संरेखण का भंडारण प्राप्त किया गया था - intवस्तु का जीवनकाल वहां से शुरू होता है।
अवकर

41

हाँ, यह यूबी था। जिन तरीकों से intअस्तित्व में लाया जा सकता है, उनकी सूची की गणना की गई थी, और कोई भी वहां लागू नहीं होता है, जब तक कि आप यह नहीं मानते हैं कि मॉलॉक एकॉज़ल है।

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

2 वें प्रश्न के लिए, C ++ यह नहीं बताता है कि C ++ और C कैसे इंटरैक्ट करते हैं। तो सी के साथ सभी बातचीत है ... यूबी, उर्फ ​​व्यवहार सी ++ मानक द्वारा अपरिभाषित।


5
क्या आप किसी इंट टू अस्तित्व के तरीकों की विस्तृत सूची पर विस्तार कर सकते हैं? मुझे याद है कि आदिम प्रकारों के जीवनकाल के बारे में एक समान प्रश्न पूछना, और बताया जा रहा है कि एक आदिम यह कहकर "अस्तित्व में" बस अस्तित्व में हो सकता है क्योंकि कल्पना ने अन्यथा नहीं कहा। ऐसा लगता है कि मैं कल्पना के एक उपयोगी खंड को याद कर सकता हूं! मुझे यह जानकर अच्छा लगेगा कि मुझे किस अनुभाग का उपयोग करना चाहिए था!
Cort Ammon

7
@CortAmmon C ++ 20 में मौजूद किसी वस्तु (किसी भी प्रकार के) के तरीकों की प्रगणित सूची [intro.object] में हैं : (1) परिभाषा (2) द्वारा नई-अभिव्यक्ति (3) नए नियमों के अनुसार P0593 (4) में एक संघ के सक्रिय सदस्य (5) को अस्थायी रूप से बदलना। (3) C ++ 20 में नया है, (4) C ++ 17 में नया था।
बैरी

3
क्या C / C ++ इंटरैक्शन वास्तव में UB है? यह अपरिभाषित होने के बजाय कार्यान्वयन-परिभाषित होने के लिए अधिक समझ में आता है, अन्यथा यह extern "C"सिंटैक्स भी बिल्कुल अजीब होगा ।
रुस्लान

4
@ रोलन: कार्यान्वयन किसी भी व्यवहार को परिभाषित करने के लिए स्वतंत्र हैं आईएसओ सी ++ अपरिभाषित हैं। (उदाहरण के लिए gcc -fno-strict-aliasing, या डिफ़ॉल्ट रूप से MSVC)। यह कहते हुए कि "कार्यान्वयन परिभाषित" को सभी C ++ कार्यान्वयन की आवश्यकता होगी ताकि वे कुछ सी कार्यान्वयन के साथ किसी तरह से परिभाषित कर सकें, इसलिए यह पूरी तरह से कार्यान्वयन को छोड़ने के लिए समझ में आता है कि वे ऐसा कुछ भी करना चाहते हैं या नहीं।
पीटर कॉर्ड्स

4
@PeterCordes: मुझे आश्चर्य है कि क्यों इतने सारे लोग IDB और UB के बीच के उस अंतर को पहचानने में विफल रहते हैं, और कुछ ऐसी काल्पनिक धारणा को अपनाते हैं कि Standard की विफलता यह बताती है कि सभी कार्यान्वयन एक निर्माण प्रक्रिया को सार्थक रूप से एक निर्णय का अर्थ देते हैं - किसी भी कार्यान्वयन से ऐसा करने की उम्मीद नहीं की जानी चाहिए। और कार्यान्वयन जो ऐसा नहीं करते हैं उन्हें परिणाम के रूप में नहीं देखा जाना चाहिए।
सुपरकैट
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.