2012-09-18 31 views
5

मुझे हाल ही में मेरे कोड पर एक बग मिला जो मुझे डीबग करने में कुछ घंटे लगा।क्यों कुछ अंतर्निहित प्रकार रूपांतरण मशीन पर सुरक्षित हैं और दूसरे पर नहीं ?? मैं इस क्रॉस प्लेटफ़ॉर्म के मुद्दों को कैसे रोक सकता हूं?

समस्या एक समारोह में परिभाषित किया गया था के रूप में:

unsigned int foo(unsigned int i){ 
    long int v[]={i-1,i,i+1} ; 
     . 
     . 
     . 
return x ; // evaluated by the function but not essential how for this problem. 
} 

वी की परिभाषा मेरे विकास मशीन (Ubuntu 12.04 32 बिट, जी ++ संकलक), जहां अहस्ताक्षरित int परोक्ष थे पर किसी भी मुद्दे का कारण नहीं लंबे int में परिवर्तित हो गया और इस तरह के नकारात्मक मान सही ढंग से संभाले गए थे।

एक अलग मशीन पर (उबंटू 12.04 64 बिट, जी ++ कंपाइलर) हालांकि यह ऑपरेशन सुरक्षित नहीं था। जब मैं = 0, वी [0] -1 पर सेट नहीं किया गया था, लेकिन कुछ अजीब बड़े मूल्य के लिए (जैसा कि अक्सर हस्ताक्षर किए गए int नकारात्मक बनाने की कोशिश करते समय होता है)।

मैं लंबे समय से पूर्णांक

long int v[]={(long int) i - 1, (long int) i, (long int) i + 1}; 

को मुद्दा मैं का मूल्य कास्टिंग का समाधान कर सकता है और सब कुछ ठीक (दोनों मशीनों पर) में काम किया।

मुझे पता नहीं लगा कि मशीन पर पहला काम ठीक क्यों होता है और दूसरे पर काम नहीं करता है।

क्या आप इसे समझने में मेरी सहायता कर सकते हैं, ताकि मैं भविष्य में इस या अन्य मुद्दों से बच सकूं?

उत्तर

6

unsigned के लिए मूल्यों, इसके अलावा/घटाव सापेक्ष गणित के रूप में अच्छी तरह से परिभाषित किया गया है, इसलिए 0U-1 बाहर कुछ करने के लिए std::numeric_limits<unsigned>::max() की तरह काम करेगा।

है, पर हस्ताक्षर किए के लिए अहस्ताक्षरित से परिवर्तित करता है, तो गंतव्य प्रकार इतना बड़ा अहस्ताक्षरित मूल्य के सभी मानों धारण करने के लिए है तो यह केवल एक सीधी डेटा गंतव्य प्रकार में कॉपी करता है। यदि गंतव्य प्रकार सभी हस्ताक्षरित मूल्यों को पकड़ने के लिए पर्याप्त नहीं है, तो मेरा मानना ​​है कि यह कार्यान्वयन परिभाषित है (मानक संदर्भ खोजने का प्रयास करेगा)।

तो long 64-बिट (संभवतः आपकी 64-बिट मशीन पर मामला) हस्ताक्षरित फिट बैठता है और सीधे कॉपी किया जाता है।

जब long 32-बिट मशीन पर 32-बिट है, इसे फिर से सबसे अधिक संभावना सिर्फ एक पर हस्ताक्षर किए मूल्य जो है -1 कि इस मामले में थोड़ा पैटर्न व्याख्या करता है।

संपादित करें: इन समस्याओं से बचने का सबसे आसान तरीका हस्ताक्षर किए गए और हस्ताक्षरित प्रकारों को मिश्रण से बचाना है। किसी ऐसे मूल्य से घटाने का क्या अर्थ है जिसका अवधारणा ऋणात्मक संख्याओं की अनुमति नहीं देता है? मैं बहस करने जा रहा हूं कि फ़ंक्शन पैरामीटर आपके उदाहरण में एक हस्ताक्षरित मान होना चाहिए।

कहा कि जी ++ (कम से कम 4.5 संस्करण) एक आसान -Wsign-conversion कि अपने विशेष कोड में इस मुद्दे का पता लगाता है प्रदान करता है।

+0

धन्यवाद।मुझे पूरी तरह से यकीन नहीं है, लेकिन मुझे याद है कि लंबे int int unsigned int के लिए पर्याप्त हैं (कम से कम कुछ सी ++ संदर्भों के अनुसार जो आप ऑनलाइन पा सकते हैं)। वैसे भी मैं मानता हूं कि अच्छा मिश्रण है कि उन्हें मिश्रण न करें, लेकिन इस मामले में मेरे लिए ऐसा करना आवश्यक है। मैं जानना चाहता था कि ये मशीन निर्भर मुद्दों कब उत्पन्न हो सकती हैं। – lucacerone

0

तुम भी सब कुछ खत्म हो प्रवाह को पकड़ने डाली विशेष हो सकता डाले:

template<typename O, typename I> 
O architecture_cast(I x) { 
/* make sure I is an unsigned type. It */ 
static_assert(std::is_unsigned<I>::value, "Input value to architecture_cast has to be unsigned"); 

assert(x <= static_cast<typename std::make_unsigned<O>::type>(std::numeric_limits<O>::max())); 

return static_cast<O>(x); 
} 

इस का उपयोग करते हुए बड़ी संख्या से डिबग में पकड़ेगा डाले के सभी से परिणामस्वरूप प्रकार समायोजित कर सकते हैं। इस 0 जा रहा है और -1 जो ​​सबसे बड़ी अहस्ताक्षरित पूर्णांक के लिए परिणाम से घटाया पूर्णांक अहस्ताक्षरित के अपने मामले भी शामिल है। स्पष्टीकरण हालांकि मैं बहुत अच्छी तरह से आपका जवाब नहीं समझ सकता है के लिए