यह कोड 64-बिट आर्किटेक्चर पर सेगफॉल्ट क्यों करता है लेकिन 32-बिट पर ठीक काम करता है?


112

मैं निम्नलिखित सी पहेली पर आया:

प्रश्न: IA-64 पर निम्न प्रोग्राम क्यों नहीं आता है, लेकिन IA-32 पर ठीक काम करता है?

  int main()
  {
      int* p;
      p = (int*)malloc(sizeof(int));
      *p = 10;
      return 0;
  }

मुझे पता है कि int64 बिट मशीन पर आकार एक सूचक के आकार के समान नहीं हो intसकता है ( 32 बिट हो सकता है और सूचक 64 बिट हो सकता है)। लेकिन मुझे यकीन नहीं है कि यह उपरोक्त कार्यक्रम से कैसे संबंधित है। कोई विचार?


50
क्या यह कुछ मूर्खतापूर्ण है जैसे stdlib.hशामिल नहीं किया जा रहा है?
user786653 12

3
यह कोड मेरी 64 बिट मशीन पर ठीक चलता है। यह भी चेतावनी के बिना संकलित करता है यदि आप #include stdlib.h(
मालॉक के

1
डी 'ओह! @ user786653 ने महत्वपूर्ण बिट को nailed किया। के साथ #include <stdlib.h>, यह पूरी तरह से मिल रहा है, लेकिन यह सवाल में नहीं है।

8
@delnan - यह उस तरह काम नहीं करता है, हालांकि, यह वैध रूप से एक मंच पर विफल हो सकता है sizeof(int) == sizeof(int*), जहां , उदाहरण के लिए पॉइंटर्स वापस आ गए, हालांकि intउपयोग किए गए कॉलिंग कन्वेंशन में एस करने के लिए एक अलग रजिस्टर ।
फ्लेक्सो

7
एक C99 वातावरण में, संकलक आपको कम से कम निहित घोषणा के बारे में चेतावनी दे रहा होना चाहिए malloc()। जीसीसी कहता है: warning: incompatible implicit declaration of built-in function 'malloc'भी।
जोनाथन लेफलर

जवाबों:


130

कलाकारों को int*इस तथ्य का सामना करना पड़ता है कि उचित #includeवापसी के बिना प्रकार mallocमाना जाता है int। IA-64 होता है sizeof(int) < sizeof(int*)जो इस समस्या को स्पष्ट करता है।

(यह भी ध्यान दें कि अपरिभाषित व्यवहार के कारण यह अभी भी एक मंच पर विफल हो सकता है जहां sizeof(int)==sizeof(int*)सच है, उदाहरण के लिए यदि कॉलिंग कन्वेंशन पूर्णांक की तुलना में लौटने वाले बिंदुओं के लिए विभिन्न रजिस्टरों का उपयोग करता है)

Comp.lang.c पूछे जाने वाले प्रश्न एक प्रवेश पर चर्चा है क्यों से लौटने के कास्टिंग mallocकी जरूरत कभी नहीं किया गया है और संभावित रूप से बुरा


5
बिना उचित # जानकारी के, क्यों मॉलॉक के प्रकार को एक इंट माना जाता है?
उपयोगकर्ता 7

11
@TP - जो newC ++ में हमेशा उपयोग करने के लिए एक अच्छा कारण है और हमेशा C कंपाइलर के साथ C संकलित करता है न कि C ++ कंपाइलर।
फ्लेक्सो

6
@ user7 - यही नियम है। किसी भी वापसी प्रकार को माना जाता है intयदि यह ज्ञात नहीं है
फ्लेक्सो

2
@vlad - बेहतर विचार हमेशा इस कारण से निहित घोषणाओं पर भरोसा करने के बजाय कार्यों की घोषणा करना है। (और से वापसी नहीं malloc)
फ्लेक्सो

16
@ user7: "हमारे पास एक सूचक p (आकार 64 का) है जो 32 बिट्स मेमोरी की ओर इशारा करता है" - गलत। मॉलॉक द्वारा आवंटित ब्लॉक का पता ए के लिए बुलाए गए सम्मेलन के अनुसार लौटाया गया था void*। लेकिन कॉलिंग कोड फ़ंक्शन रिटर्न के बारे में सोचता है int(चूंकि आपने इसे अन्यथा नहीं बताने का विकल्प चुना है), इसलिए यह कॉलिंग कन्वेंशन के अनुसार रिटर्न वैल्यू को पढ़ने की कोशिश करता है int। इसलिए आवश्यक रूप से आवंटित स्मृति को इंगित नहींp करता है । यह सिर्फ IA32 के लिए काम करने के लिए हुआ क्योंकि a और a समान आकार के हैं, और उसी तरह वापस आए। IA64 पर आपको गलत मान मिलता है। intvoid*
स्टीव जेसप

33

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

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

यही कारण है कि आपने सी में रिटर्न कभी नहीं डाला mallocहै। void*यह रिटर्न स्पष्ट रूप से सही प्रकार के पॉइंटर में परिवर्तित हो जाएगा (जब तक कि आपने हेडर को शामिल नहीं किया है, तो इस मामले में संभवतः आपको संभावित असुरक्षित इंट की चेतावनी दी होगी- को-सूचक रूपांतरण)।


भोली लगने के लिए खेद है, लेकिन मैंने हमेशा माना कि मॉलोक एक शून्य सूचक देता है जिसे एक उपयुक्त प्रकार में डाला जा सकता है। मैं सी प्रोग्रामर नहीं हूं और इसलिए थोड़ा और विस्तार की सराहना करूंगा।
उपयोगकर्ता 7

5
@ user7: बिना #include <stdlib.h> सी कंपाइलर मानता है कि मॉलॉक का रिटर्न वैल्यू एक इंट है।
शशांग

4
@ user7: शून्य पॉइंटर को कास्ट किया जा सकता है, लेकिन इसकी सी में जरूरत नहीं है क्योंकि void *इसे किसी अन्य पॉइंटर प्रकार में परिवर्तित किया जा सकता है। int *p = malloc(sizeof(int))काम करता है अगर उचित प्रोटोटाइप गुंजाइश में है और विफल रहता है अगर यह नहीं है (क्योंकि तब परिणाम माना जाता है int)। कलाकारों के साथ, दोनों संकलन करेंगे और उत्तरार्द्ध में त्रुटियों का परिणाम होगा sizeof(int) != sizeof(void *)

2
@ user7 लेकिन यदि आप शामिल नहीं हैं stdlib.h, तो संकलक को पता नहीं है mallocऔर न ही इसका रिटर्न प्रकार। तो यह सिर्फ intडिफ़ॉल्ट के रूप में मानता है ।
क्रिश्चियन राऊ

10

यही कारण है कि आप कभी भी लापता प्रोटोटाइप के बारे में चेतावनी के बिना संकलन नहीं करते हैं।

यही कारण है कि आपने सी में मॉलोक रिटर्न कभी नहीं डाला।

C ++ संगतता के लिए कलाकारों की आवश्यकता है। इसे छोड़ने का कोई कारण नहीं है (पढ़ें: कोई कारण नहीं है)।

C ++ संगतता की हमेशा आवश्यकता नहीं होती है, और कुछ मामलों में यह संभव नहीं है, लेकिन ज्यादातर मामलों में यह बहुत आसानी से प्राप्त होता है।


22
यदि मेरा C कोड C ++ के साथ "संगत" है, तो मुझे पृथ्वी पर क्यों परवाह होगी? मुझे परवाह नहीं है अगर यह पर्ल या जावा या एफिल या ... के साथ संगत है
स्टीफन कैनन

4
यदि आप किसी को गारंटी देते हैं कि लाइन आपके सी कोड को देखने नहीं जा रही है और जाओ, तो मैं इसे C ++ कंपाइलर के साथ संकलित करने जा रहा हूं क्योंकि यह काम करना चाहिए!
स्टीवन लू

3
यही कारण है कि अधिकांश सी कोड को तुच्छ रूप से C ++ संगत बनाया जा सकता है ।
जिज्ञासु
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.