2012-06-28 11 views
5

मैंने लॉल्म/कंपाइलर-आरटी/क्लैंग की 3.1 रिलीज बनाई है, और मैं यह देखने की कोशिश कर रहा हूं कि -फैच-अपरिभाषित-व्यवहार वास्तव में कुछ भी करता है या नहीं। अब तक, कोई भाग्य नहीं है। जैसे मैं संकलन औरक्लैंग्स -फैच-अपरिभाषित-व्यवहार विज्ञापन के रूप में काम नहीं कर रहा है

#include <stdio.h> 
#include <stdlib.h> 

int main() { 
    int* x = malloc(sizeof(int) * 10); 
    printf("%d\n", x[20]); 
    return 0; 
} 

$ /usr/local/bin/clang -fcatch-undefined-behavior undef_test.c && ./a.out 
0 

मैं वास्तव में सरल कुछ कमी कर रहा हूँ के साथ

चला सकता हूँ?

+2

हां, आप गायब हैं कि पकड़ने/सभी/अपरिभाषित व्यवहार एक अविश्वसनीय रूप से कठिन समस्या है, जो एक संकलक को कार्यान्वित करने के लिए बहुत कठिन है। – PlasmaHH

+1

-फैड्रेस-सैनिटाइज़र को इसे पकड़ना चाहिए, जैसा कि वाल्ग्रिंड होना चाहिए। –

+0

धन्यवाद, एम्ब्रोज़। यह सबसे उपयोगी था। – Oleg2718281828

उत्तर

4

हां: x एक सरणी नहीं है।

documentation से:

-fcatch-अपरिभाषित-व्यवहार: क्रम कोड पीढ़ी को चालू अपरिभाषित व्यवहार के लिए जाँच करने के लिए। यह विकल्प, जो बंद हो जाता है, नियंत्रित करता है कि क्लैंग अपरिभाषित रनटाइम व्यवहार के लिए रनटाइम चेक जोड़ता है या नहीं। यदि कोई चेक विफल रहता है, तो __builtin_trap() विफलता को इंगित करने के लिए उपयोग किया जाता है। चेकों हैं:

  • Subscripting जहां एक संकार्य के स्थिर प्रकार एक चर जो एक सरणी प्रकार से सड़ा हुआ है और अन्य संकार्य सरणी के आकार से अधिक या शून्य से कम है।
  • शिफ्ट ऑपरेटर जहां स्थानांतरित की गई राशि बाएं हाथ की तरफ से प्रचारित बिट-चौड़ाई या शून्य से कम है।
  • यदि नियंत्रण प्रवाह __builtin_unreachable तक पहुंचता है।
  • जब llvm अधिक __builtin_object_size समर्थन लागू करता है, तो __builtin_object_size इंगित करता है कि हम मान्य स्मृति तक नहीं पहुंच रहे हैं। बिट-फ़ील्ड और वैक्टर अभी तक चेक नहीं किए गए हैं।

मैं तुम्हें subscripting जांच परीक्षण करने के लिए, दुर्भाग्य से आप एक सरणी का निर्माण नहीं किया चाहता था लगता है: आप (malloc से) स्मृति के एक क्षेत्र का निर्माण किया और फिर एक सरणी के रूप में यह व्याख्या करने के लिए चुना है; लेकिन कंपाइलर के दृष्टिकोण से यह केवल स्मृति का एक हिस्सा है (malloc के रिटर्न प्रकार की तुलना में याद रखें void* है)।

int main() { 
    int x[10] = {}; 
    printf("%d\n", x[20]); 
} 

अन्यथा, एक विशिष्ट स्मृति मुद्दों पर नजर के लिए, आप प्लगइन प्रक्षालक पता ध्यान देना चाहिए:

आप शायद के साथ इस व्यवहार का परीक्षण कर सकता है।

+0

यह क्लैंग द्वारा चेतावनी ट्रिगर करने लगता है कि '-फैच-अपरिभाषित-व्यवहार' निर्दिष्ट है या नहीं। – detly

+0

@detly: '-fcatch-undefined-behavior' एक कोड जनरेशन विकल्प है, जो चेतावनियों से संबंधित नहीं है; इसके बजाए यह रनटाइम दावे डालेगा और प्रोग्राम को क्रैश करेगा (भरोसेमंद) उन किसी भी दावे का उल्लंघन किया जाना चाहिए। बेशक, संकलन शुरू होने के तुरंत बाद चेतावनी और कार्य पर भरोसा करना बेहतर होता है। ध्यान दें कि '-फैच-अपरिभाषित-व्यवहार' अब बहिष्कृत है और आपको विभिन्न पता/मेमोरी/थ्रेड/अपरिभाषित sanitizers को सक्रिय करने के लिए '-fsanitize' का उपयोग करना चाहिए (और ध्यान रखें कि उनमें से कुछ एक दूसरे के साथ असंगत हैं) । –

1

-fcatch-undefined-behavior यादृच्छिक सूचक dereferences संभाल नहीं करता है। इस मामले को संभालने के लिए, कंपाइलर को पॉइंटर के साथ पॉइंट डेटा के आकार को स्टोर करना होगा और उस फंक्शन कॉल में उस आकार को पास करना होगा। यह मौजूदा एबीआई के साथ असंगत होगा और आपके कार्यक्रम से जुड़े सभी पुस्तकालयों को पुन: संकलित करने की आवश्यकता होगी।

आप तर्क दे सकते हैं कि malloc एक प्रसिद्ध कार्य है और संकलक अनुरोधित आकार की एक सरणी में लौटाए गए पॉइंटर बिंदुओं को मान सकता है।

लेकिन आप भूल जाएंगे कि mallocNULL वापस आ सकता है। यदि संकलक मानता है कि सूचक NULL नहीं है, तो यह किसी भी NULL जांच (काफी खतरनाक) को अनुकूलित करेगा।यदि संकलक ने माना कि सूचक NULL है या अनुरोधित आकार की एक सरणी के लिए एक सूचक है, तो यह प्रबंधित करने के लिए थोड़ा जटिल हो जाएगा (और हमने free और realloc अभी तक बात नहीं की है)। इसके अलावा malloc-दिनांकित पॉइंटर NULL जांच के बिना किसी भी कोड को अपरिभाषित व्यवहार के रूप में माना जाएगा।

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

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