2016-06-07 7 views
14

वहाँ this answer जो मानक malloc की तरह वापसी मान के रूप में एक void* गुजर के बजाय उत्पादन तर्क के रूप में उपयोग करता void**cudaMalloc((void**)&device_array, num_bytes) का उपयोग करते हैं, के बारे में एक और सवाल पर है।कास्टिंग (शून्य **) और device_array जैसे कास्टिंग में क्या गलत है?

यह NVIDIA के एपीआई की आलोचना की और कहा गया है: में (शून्य **) & device_array रूप

कास्टिंग, अवैध सी और अपरिभाषित व्यवहार में परिणाम है।

और कई बार (8 अभी तक) को उखाड़ फेंक दिया गया है, इसलिए मुझे लगता है कि इसमें कुछ सच्चाई है।

मुझे समझ नहीं आता क्या वहाँ कास्टिंग साथ कुछ गड़बड़ है।

  • क्या अमान्य सी यहाँ है?
  • किस मामले में यह अपरिभाषित व्यवहार का कारण बन जाएगा?

मुझे पता है कि यह चेतावनी के बिना संकलित करता है और मेरे लिए इच्छित व्यवहार के साथ चलता है। लेकिन मैं सी मानक विनिर्देश स्तर तक सी के साथ जानकार नहीं हूँ।

+0

वही समस्या जैसे कि आपने 'int *' 'float *' पर डाला है। 'शून्य **' 'void *' वैसे ही विशेष नहीं है। – immibis

+0

फिर, क्या यह लिखना गलत है? 'int val = 0x4229B26C; \t printf ("0x% एक्स द्वारा स्मृति में प्रदर्शित फ्लोट का% .03f \ n", वैल, * ((फ्लोट *) &val)); ' – bct

+0

का दशमलव मान है [यह SO पोस्ट] (http://stackoverflow.com/questions/15818906/does-this-pointer-casting-break-strict-aliasing-rule) – LPs

उत्तर

8

समस्या यह है कि void* सी में एक विशेष अर्थ, विशेष नियम (1) के साथ है। यह एकमात्र सूचक प्रकार है/जिससे आप किसी भी अन्य सूचक प्रकार को सुरक्षित रूप से परिवर्तित कर सकते हैं। हालांकि, ये विशेष नियम void** पर पुनरावर्ती रूप से लागू नहीं होते हैं।

मतलब int* ptr = malloc(x); की तरह है कि कोड पूरी तरह से ठीक है, लेकिन

int* ptr; 
cudaMalloc(&ptr, x); // bad 

ठीक नहीं है! int** से void** से एक सूचक रूपांतरण अच्छी तरह से परिभाषित नहीं है। सिद्धांत रूप में यह अपरिभाषित व्यवहार और misalignment (2) का कारण बन सकता है।

अलावा, वहाँ भी सूचक अलियासिंग के साथ समस्याओं हो सकता है। संकलक यह मानने के लिए स्वतंत्र है कि void** की सामग्री को कभी भी int** के माध्यम से एक्सेस नहीं किया जाता है और इसलिए अप्रत्याशित तरीकों से कोड को अनुकूलित कर सकता है, जिससे सख्त एलियासिंग नियम (6.5) का उल्लंघन करने के लिए अपरिभाषित व्यवहार होता है।

इसका मतलब है आप सुरक्षित रूप से समारोह का उपयोग करने के क्रम में इस तरह कोड लिखने के लिए करना होगा:

void* vptr; 
int* iptr; 

cudaMalloc(&vptr, x); 
iptr = vptr; 

(1) सी 11 6.3.2.3/1:

एक संकेतक शून्य के लिए किसी ऑब्जेक्ट को प्रकार में किसी पॉइंटर में या उससे परिवर्तित किया जा सकता है। किसी ऑब्जेक्ट प्रकार के लिए पॉइंटर को पॉइंटर में शून्य में बदल दिया जा सकता है; परिणाम मूल सूचक के बराबर की तुलना करेगा।

(2) सी 11 6.3.2।3/7:

एक वस्तु प्रकार के लिए एक सूचक एक अलग ऑब्जेक्ट प्रकार के सूचक के लिए परिवर्तित किया जा सकता है। यदि परिणामस्वरूप सूचक सही ढंग से संदर्भित प्रकार के लिए गठबंधन नहीं है, तो व्यवहार अपरिभाषित है।

+0

मुझे वास्तव में नहीं पता कि एपीआई भयानक चीज़ कहां से उत्पन्न हुई है। ऐसा लगता है कि सभी कार्य डिवाइस_एरे को '' शून्य * '' ले लो, इसलिए कहीं भी 'int *' 'का उपयोग करने की आवश्यकता नहीं है। शायद दूसरे प्रश्न का उदाहरण कोड ही एकमात्र भयानक बात है। – atturri

+0

@atturri' void * 'एक नहीं है सार्थक प्रकार अपने आप से। कहीं कार्यक्रम में, इच्छित प्रकार में एक रूपांतरण होगा। लेकिन अगर वह रूपांतरण हमेशा एक अमूर्त परत के पीछे छिपा रहता है, तो एपीआई ठीक हो सकती है। मुझे वास्तव में कुडा के बारे में कुछ भी पता नहीं है इसलिए मैं नहीं बता सकता। मैं इसके बारे में अपनी टिप्पणी हटा दूंगा, क्योंकि यह किसी भी संदर्भ के बिना व्यक्तिपरक है। – Lundin

+0

@ लुंडिन अच्छा जवाब। अटुरी की टिप्पणी के बारे में, कूडा मेमोरी आवंटन शून्य के मामले में * कम से कम मेजबान कोड पर किसी और चीज़ में परिवर्तित नहीं किया जाना चाहिए। असल में यह ग्राफिक्स मेमोरी में एक पते को इंगित करता है जो सीपीयू द्वारा उपलब्ध नहीं है ... तो इसके बारे में सोचने के बाद, मैं तर्क दूंगा कि समस्या यह है कि डिवाइस_एरे का प्रकार शून्य होना चाहिए और int * नहीं होना चाहिए? तो सबकुछ ठीक होगा? .... – bct

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