2012-04-21 33 views
5

मैं कुछ के लिए malloc का उपयोग कर एक कोड लिख रहा था और फिर एक मुद्दा का सामना करना पड़ा तो मैं एक परीक्षण कोड है जो वास्तव में पूरी भ्रम जो नीचे है ::गतिशील स्मृति आवंटन मुद्दे

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

int main()  
{ 
    int *p = NULL; 
    void *t = NULL; 
    unsigned short *d = NULL; 

    t = malloc(2); 
    if(t == NULL) perror("\n ERROR:"); 
    printf("\nSHORT:%d\n",sizeof(short)); 
    d =t; 
    (*d) = 65536; 
    p = t; 
    *p = 65536; 
    printf("\nP:%p: D:%p:\n",p,d); 
    printf("\nVAL_P:%d ## VAL_D:%d\n",(*p),(*d)); 
    return 0; 
    } 
    Output:: [email protected]:~/Desktop/ad/A1/CC$ ./test 

      SHORT:2 
      P:0x9512008: D:0x9512008: 
      VAL_P:65536 ## VAL_D:0 

का सार लिखा था मैं malloc का उपयोग कर स्मृति के 2 बाइट आवंटित कर रहा हूं। मॉलोक जो लौटाता है एक शून्य * सूचक एक शून्य * सूचक 'टी' में संग्रहीत किया जाता है।

उसके बाद 2 पॉइंटर्स घोषित किए गए हैं पी - पूर्ण प्रकार का पूर्णांक प्रकार और डी। तो मैंने उन दोनों को टी * (पी = टी और डी = टी) * का मतलब है कि दोनों डी & पी ढेर पर एक ही ज्ञापन स्थान पर इंगित कर रहे हैं।

65536 (2^16) से (* डी) को बचाने की कोशिश करने पर मुझे चेतावनी मिलती है कि बड़े int मान को छोटा कर दिया जाता है। अब मैंने फिर से 65536 (2^16) से (* पी) बचाया जिसने कोई चेतावनी नहीं दी।

* प्रिंटिंग (* पी) और (डी) पर मुझे अलग-अलग मान मिलते हैं (हालांकि प्रत्येक निर्धारित परिभाषित सूचक प्रकार के लिए सही है)।

मेरा प्रश्न हैं:

  1. हालांकि मैं ढेर मेम malloc का उपयोग कर के 2 बाइट्स (यानी 16 बिट) आवंटित मैं कैसे उन दो बाइट्स में 65536 (बचाने में सक्षम का उपयोग करके कर रहा हूँ (पी) जो पूर्णांक प्रकार का सूचक है) .?? मुझे यह एहसास है कि इसका कारण शून्य * सूचक (पी = टी में) शून्य के स्वचालित प्रकार का कनवर्टन है, इसलिए यह है कि एम को पी को असाइन करने के लिए एमएलओसी के माध्यम से आवंटित किए गए मेमोरी क्षेत्रों तक पहुंच प्राप्त होती है। ??।

  2. भले ही यह सब हो रहा है, वही स्मृति क्षेत्र (* पी) और (* डी) के माध्यम से दो अलग-अलग उत्तरों प्रिंट करता है (हालांकि यह भी समझाया जा सकता है कि क्या मैं प्रश्न 1 में कारण सोच रहा हूं)।

किसी यदि कुछ भी इस के पीछे के कारणों की व्याख्या कर सकते इस पर कुछ प्रकाश डाल सकते हैं, यह वास्तव में भी appreciated..and हो जाएगा ..

बहुत धन्यवाद

+0

मॉलोक अनुरोध किए गए आकार को एक निश्चित गुणक की ओर ले जा रहा है। * निक्स के बारे में नहीं जानते, लेकिन विंडोज 8 बाइट्स के गुणकों तक इसे गोल करना पसंद करते हैं। यदि ऐसा है, तो आप अनुरोध किए गए क्षेत्र के बाहर लिख रहे हैं, लेकिन यह सुरक्षा मार्जिन के भीतर होता है, और इसलिए आप किसी और चीज को दूषित नहीं कर रहे हैं। – DCoder

+0

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

+0

@dmckee मुझे पता है कि मैं जो कर रहा हूं वह नहीं किया जाना चाहिए, लेकिन इस पर ठोकर खाने के बाद मैं इसके पीछे के सटीक कारणों को जानने के लिए उत्सुक था, जिसे मैंने शुरू में अनुमान लगाया था कि 2 बाइट आवंटित शून्य * सूचक के int * में स्वचालित प्रकार रूपांतरण int * पॉइंटर को अधिक मेमोरी के बाद 2 बाइट्स तक पहुंच जाता है क्योंकि मेरी मशीन int पर 4 बाइट्स है। क्या यह सही है (मेरी धारणा) – abhi

उत्तर

2

पहले अपने दूसरे प्रश्न का उत्तर देना:

स्पष्टीकरण तथ्य यह है कि एक int आम तौर पर 4 बाइट्स की है, और सबसे महत्वपूर्ण बाइट्स पहले दो पदों में संग्रहित किया जा सकता है।एक short, जो केवल 2 बाइट्स है, अपने डेटा को पहले दो स्थितियों में भी संग्रहीत करता है। जाहिर है, तो, एक int और एक short में 65536 भंडारण, लेकिन एक ही स्मृति स्थान पर ओर इशारा करते हुए, कारण होगा डेटा दो int के कम से कम महत्वपूर्ण बाइट्स के साथ short के संबंध में int के लिए दो बाइट्स की भरपाई संग्रहीत करने के लिए, short के लिए भंडारण के अनुरूप।

इसलिए, जब संकलक प्रिंट *d, यह एक short के रूप में इस व्याख्या करती है और क्षेत्र में एक short के लिए भंडारण के लिए इसी है, जो नहीं है, जहां संकलक पहले 65536 संग्रहीत की जाने वाली *p लिखा गया था पर लग रहा है। ध्यान दें कि *p = 65536; लिखना पिछले *d = 65536; को ओवरराइट करता है, 0 के साथ दो कम से कम महत्वपूर्ण बाइट्स को पॉप्युलेट करता है।

पहला सवाल के बारे में: संकलक नहीं दुकान *p 2 बाइट्स के भीतर के लिए 65536 करता है। यह बस आपके द्वारा आवंटित स्मृति की सीमाओं के बाहर जाता है - जो किसी बिंदु पर एक बग का कारण बन सकता है।

+0

तो तथ्य यह है कि एक 2 बाइट आवंटित शून्य * के सूचकांक में स्वचालित प्रकार रूपांतरण * सूचक * int * पॉइंटर को और अधिक मेमोरी के बाद 2 बाइट्स तक पहुंच जाता है क्योंकि मेरी मशीन int 4 बाइट्स है। क्या यह सही है (मेरी धारणा) – abhi

+0

और स्पष्ट और कुरकुरा उत्तर के लिए धन्यवाद जो सबकुछ बताता है :) – abhi

+1

संकल्पनात्मक रूप से, यही वह है। मैं कहूंगा कि तकनीकी रूप से बोलते हुए, शायद यह आपके वाक्य में "स्वचालित प्रकार रूपांतरण" कहने का सबसे अच्छा शब्द नहीं है, क्योंकि वास्तव में कुछ भी परिवर्तित नहीं किया जा रहा है - यह सिर्फ इतना है कि संकलक स्मृति में बाइट्स तक पहुंच रहा है जैसे कि वे एक प्रकार का संग्रह कर रहे हैं डेटा का उपयोग करने के विरोध में, जैसे कि वे एक और प्रकार संग्रहित कर रहे हैं। –

1

सी में आवंटन की सीमाओं से बाहर लिखने के लिए बिल्कुल कोई सुरक्षा नहीं है। बस ऐसा मत करो, कुछ भी हो सकता है। यहां ऐसा लगता है कि यह आपके लिए काम करता है क्योंकि कुछ संयोग से आपके द्वारा आवंटित दो बाइट्स के पीछे की जगह किसी अन्य चीज़ के लिए उपयोग नहीं की जाती है।

+0

या कम से कम उसने ऐसा कुछ भी नहीं किया है जो उस स्मृति के लिए कुछ अन्य उपयोग प्रदर्शित करता है। इस तरह की त्रुटि के लिए चुप्पी प्रतिक्रिया यह है कि उन्हें आप पर चुपके देता है। – dmckee

0

1) ओएस मेमोरी मैनेजर की ग्रैन्युलरिटी 4K है। एक बिट द्वारा एक ओवीराइट एक एवी/सेगफॉल्ट ट्रिगर करने की संभावना नहीं है, लेकिन यह आसन्न स्थान में किसी भी डेटा को दूषित कर देगा, जिससे:

2) अपरिभाषित व्यवहार। व्यवहार के इस सेट में 'अपरिवर्तनीय रूप से सही संचालन' शामिल है, (अभी के लिए!)।

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