2016-08-30 5 views
5

मैंने अभी Bug in VC++ 14.0 (2015) compiler? से सीखा है कि किसी को यह नहीं समझना चाहिए कि स्ट्रक्चर का लेआउट स्मृति में कैसे समाप्त होगा। हालांकि, मुझे समझ में नहीं आता कि मैंने कितने कोड में देखा है।कोई सी ++ स्ट्रक्चर लेआउट के बारे में धारणा कैसे नहीं बना सकता है?

uboVS.model = ... 
    uboVS.... 

तो बस struct से अधिक प्रतियां (मेजबान स्मृति में) करने के लिए:

एक struct

struct { 
    glm::mat4 projection; 
    glm::mat4 model; 
    glm::vec4 lightPos; 
} uboVS; 

तो अपने खेतों भरता को परिभाषित करता है: उदाहरण के लिए, Vulkan ग्राफिक्स एपीआई निम्नलिखित करता है memcpy के माध्यम से डिवाइस मेमोरी:

uint8_t *pData; 
    vkMapMemory(device, memory, 0, sizeof(uboVS), 0, (void **)&pData); 
    memcpy(pData, &uboVS, sizeof(uboVS)); 
    vkUnmapMemory(device, memory); 

फिर GPU पर, यह उस यूआरबी को उस stru से मेल खाने के लिए परिभाषित करता है सीटी:

layout (binding = 0) uniform UBO 
{ 
    mat4 projection; 
    mat4 model; 
    vec4 lightPos; 
} ubo; 

फिर, जीपीयू पक्ष पर, यूबो हमेशा यूबोवीएस से मेल खाता है।

क्या यह वही अपरिभाषित व्यवहार है? क्या वह कोड यूबीओवीएस संरचना पर निर्भर नहीं है, जैसा कि परिभाषित किया गया है, या दोनों तरफ (संकलित सी ++ कोड और संकलित एसपीआईआर-वी शेडर) मूल रूप से एक ही अलग संरचना लेआउट उत्पन्न करने के लिए? (https://www.securecoding.cert.org/confluence/display/c/EXP11-C.+Do+not+make+assumptions+regarding+the+layout+of+structures+with+bit-fields में पहले उदाहरण के समान)

यह प्रश्न वल्कन या ग्राफिक्स एपीआई के लिए विशिष्ट नहीं है, मैं उत्सुक हूं कि वास्तव में क्या लगता है और स्मृति के एक हिस्से के रूप में संरचना का उपयोग करना ठीक है। मैं संरचना पैकिंग और संरेखण को समझता हूं, लेकिन इसके लिए और भी कुछ है?

धन्यवाद

+2

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

+1

आप [इस प्रश्न और उत्तर] को देखना चाह सकते हैं। (Http://stackoverflow.com/questions/38428666/why-can-glbufferdata-buffer-structs-for-ubo-and-ssbo-when-c-does -नॉट-निर्दिष्ट-एस/38429253 # 38429253) –

+0

संरचना लेआउट के बारे में धारणाओं से बचने के लिए, structs पर 'memcpy' का उपयोग न करें (अन्य चीजों के साथ) –

उत्तर

7

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

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

इसके विपरीत, एक बाइट सरणी में एक संरचना को परिवर्तित करना और उस सरणी को कहीं और कॉपी करना वास्तव में C++ ऑब्जेक्ट मॉडल के नियमों को तोड़ता नहीं है। इसमें उचित प्रकार के लिए ऐसी चीजों को अनुमति देने वाला एक बहुत ही विशिष्ट खंड है।

अंतर यह है कि यह सी ++ कंपाइलर नहीं है जो ऑब्जेक्ट के लेआउट की परवाह करता है; यह जीपीयू है। जब तक आप प्रदान करते हुए डेटा का लेआउट मेल खाता है, तो आपके शेडर ने कहा कि यह ठीक होगा, आप ठीक हैं। आप अरणों में फ्लोट्स कास्टिंग नहीं कर रहे हैं या एक ऑब्जेक्ट को एक पॉइंटर के माध्यम से एक अलग या किसी चीज़ तक पहुंचने का प्रयास नहीं कर रहे हैं। आप बस बाइट कॉपी कर रहे हैं।

किस बिंदु पर, एकमात्र सवाल यह है कि यह है कि उस संरचना का बाइट प्रतिनिधित्व अपेक्षित एसपीआईआर-वी डेटा संरचना परिभाषा के बाइट प्रतिनिधित्व से मेल खाता है या नहीं। और हाँ, this is something you can rely upon for most systems that Vulkan can run on

5

ऐसा नहीं है कि मोटे तौर पर कहा जाए तो सी ++ मानक वर्ग के सदस्यों के किसी विशेष आंतरिक लेआउट जनादेश नहीं है सच है।

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

ऑपरेटिंग सिस्टम जिनमें एक से अधिक कंपाइलर होते हैं, उस ऑपरेटिंग सिस्टम की बाइनरी एबीआई के लिए औपचारिक विनिर्देशन होता है, और कंपेलर उस एबीआई का पालन करने जा रहे हैं, और विशेषता पुस्तकालय कक्षा और संरचना परिभाषाएं प्रदान करेगा जो सिंक में होंगे उस के साथ।

तो, अपने विशिष्ट मामले में, आप अपने कंपाइलर के दस्तावेज़ों से परामर्श करने के बाद "मान लें और स्मृति के एक हिस्से के रूप में केवल संरचना का उपयोग करना ठीक है", यह निर्धारित करें कि आपका कंपाइलर संरचनाओं या कक्षाओं के सदस्यों को कैसे बताता है , और उसके बाद एक संरचना लेआउट के साथ आते हैं।

0

स्पिर-वी (आप जिस श्लेडिंग भाषा को वल्कन में पास करते हैं) के लिए आवश्यक है कि आप यूनिफॉर्म कॉन्स्टेंट, वर्दी और पुशकोनस्टेंट चर के लिए प्रयुक्त सदस्यों के लिए लेआउट सजावट जोड़ें। आप इसका उपयोग कर सकते हैं ताकि स्पिर-वी सदस्य ऑफ़सेट सी ++ स्ट्रक्चर में सदस्य ऑफ़सेट से मेल खाते हैं।

वास्तव में ऐसा करने के लिए यह मुश्किल है क्योंकि इसे स्पिर-वी कोड का निरीक्षण करने और आवश्यकतानुसार ऑफ़सेट सेट करने की आवश्यकता होती है।

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