2015-03-05 4 views
5

मैंने लिनक्स और विंडोज ओएस के मेमोरी मैनेजमेंट तनाव परीक्षण की जांच करने के लिए एक कोड लिखा था। बस आगे के परीक्षणों के लिए मैंने आगे बढ़कर जांच की कि मैलोक() द्वारा लौटाई गई मेमोरी में कौन से मूल्य मौजूद हैं।क्या मॉलोक (और उसके चचेरे भाई) द्वारा लौटाई गई स्मृति खंड शून्य से शुरू हुई है?

वापस आने वाले मान सभी 0 (शून्य) हैं। मैंने विंडोज और लिनक्स दोनों पर मैलोक के मैन पेज को पढ़ा है, लेकिन मैं इस व्यवहार के कारण को खोजने में सक्षम नहीं हूं। मैनपेज के अनुसार

malloc() फ़ंक्शन आकार बाइट आवंटित करता है और आवंटित स्मृति में एक सूचक देता है। स्मृति शुरू नहीं हुई है।

मेमोरी सेगमेंट को साफ़ करने के लिए, किसी को मैन्युअल रूप से memset() का उपयोग करना होगा।

#include <stdio.h> 
#include <stdlib.h> 
#include <string.h> 
#include <ctype.h> 
#include <stdbool.h> 

int eat(long total,int chunk){ 
    long i; 
    for(i=0;i<total;i+=chunk){ 
     short *buffer=malloc(sizeof(char)*chunk);  
     if(buffer==NULL){ 
      return -1; 
     } 
     printf("\nDATA=%d",*buffer); 
     memset(buffer,0,chunk); 
    } 
    return 0; 
} 

int main(int argc, char *argv[]){ 
    int i,chunk=1024; 
    long size=10000; 
      printf("Got %ld bytes in chunks of %d...\n",size,chunk); 
      if(eat(size,chunk)==0){ 
       printf("Done, press any key to free the memory\n"); 
       getchar(); 
      }else{ 
       printf("ERROR: Could not allocate the memory"); 
      } 
     } 

शायद मुझे कुछ याद आ रहा है। कोड से here

संपादित अनुकूलित है: समस्या जीसीसी विशिष्ट उत्पादन के लिए here उत्तर दिया गया गया है। मेरा मानना ​​है कि विंडोज ऑपरेटिंग सिस्टम भी एक ही प्रक्रिया का पालन करेगा।

उत्तर

12

malloc() द्वारा लौटाई गई स्मृति प्रारंभ नहीं की गई है, जिसका अर्थ है कि यह कुछ भी हो सकता है। यह शून्य हो सकता है, और यह नहीं हो सकता है; 'प्रारंभ नहीं किया गया' का अर्थ है कि यह कुछ भी हो सकता है (शून्य शामिल)। गारंटीकृत शून्य पृष्ठ प्राप्त करने के लिए calloc() का उपयोग करें।

कारण आप शून्य पृष्ठों (लिनक्स पर वैसे भी) देख रहे हैं, यह है कि यदि कोई एप्लिकेशन नए पृष्ठों का अनुरोध करता है, तो इन पृष्ठों को ओएस द्वारा शून्य किया जाता है (या अधिक सटीक वे ज़ीरो के एक निश्चित पृष्ठ की कॉपी-ऑन-राइट छवियां हैं 'वैश्विक शून्य पृष्ठ' के रूप में जाना जाता है)। लेकिन अगर malloc() पहले से ही उस एप्लिकेशन को आवंटित स्मृति का उपयोग करता है जिसे बाद में मुक्त किया गया है (ढेर का विस्तार करने के बजाए) तो आप गैर-शून्य डेटा देख सकते हैं। ध्यान दें कि ओएस द्वारा प्रदान किए गए पृष्ठों की शून्यिंग एक ओएस विशिष्ट विशेषता है (मुख्य रूप से सुरक्षा के लिए वहां है ताकि एक प्रक्रिया किसी अन्य प्रक्रिया से डेटा वाले पृष्ठों के साथ समाप्त न हो), और सी मानक द्वारा अनिवार्य नहीं है। कि कहते हैं, 'get_free_page() एक पैरामीटर, एक प्राथमिकता लेता है:

आप पृष्ठ के शून्यीकरण get_free_page के लिए एक source के लिए कहा। ... यह free_page_list का एक पृष्ठ बंद करता है, mem_map अद्यतन, पेज पृष्ठ को शून्य करता है और पृष्ठ का भौतिक पता देता है। 'Here की एक और पोस्ट जो इसे अच्छी तरह से समझाती है, और यह भी बताती है कि calloc() का उपयोग malloc() + memset() से बेहतर क्यों है।

ध्यान दें कि आप शून्य के लिए पूरे आवंटित हिस्से की जांच नहीं कर रहे हैं।

int n; 
char nonzero=0; 
char *buffer=malloc(sizeof(char)*chunk);  
if(buffer==NULL){ 
    return -1; 
} 
for (n = 0; n<chunk; n++) 
    nonzero = nonzero || buffer[n]; 
printf("\nDATA=%s\n",nonzero?"nonzero":"zero"); 
+0

पर भरोसा करते हैं तो अन्य सिस्टम पर असफल हो सकता है। क्या आप बिंदु के लिए कुछ संदर्भ साझा कर सकते हैं "इन पृष्ठों को ओएस द्वारा शून्य किया गया है।" धन्यवाद – coder

+0

@ मिस्टिकिक एक अच्छा जवाब देता है: http://stackoverflow.com/a/8029624/944201 – xmoex

+1

मुझे कभी भी 'तार्किक-या-बराबर' को पहले कभी नहीं देखा गया है ... –

2

आप बिल्कुल सही हैं; इस व्यवहार को सी भाषा मानक द्वारा गारंटी नहीं है।

जो आप देख रहे हैं वह केवल मौका हो सकता है (आप केवल प्रत्येक आवंटन में कुछ बाइट्स की जांच कर रहे हैं), या यह एक आर्टिफैक्ट हो सकता है कि आपकी ओएस और सी रनटाइम लाइब्रेरी कैसे स्मृति आवंटित कर रही है।

+0

धन्यवाद @ स्पष्टीकरण के लिए ओलिवर, लेकिन हालांकि मैन पेज का कहना है कि खंड शुरू नहीं हुआ है, लेकिन मुझे जो हिस्सा मिलता है वह प्रारंभ होता है। ऑपरेटिंग सिस्टम प्रारंभिक कर रहा है? – coder

+0

कोई भी नहीं कहता है कि पहले से ही एक निश्चित मूल्य पर सेट स्मृति को वापस करने के लिए मना किया गया है ... लेकिन इसकी गारंटी नहीं है और यदि आप इस पर भरोसा करते हैं तो – xmoex

0

इस बयान के साथ:: आप कुछ इस तरह (untested) चाहते

printf("\nDATA=%d",*buffer); 

आप केवल बाइट्स के पहले sizeof(short) राशि है कि सिर्फ malloc() 'एड (आमतौर पर दो (2) बाइट्स किया गया है की जाँच)।

इसके अलावा, पहली बार जब आप सभी शून्य प्राप्त करने के भाग्यशाली हो सकते हैं लेकिन आपके प्रोग्राम को ढेर मेमोरी निष्पादित (और उपयोग) करने के बाद सामग्री-बाद -malloc() को अनिर्धारित किया जाएगा।

0

मेमोरी आवंटन फ़ंक्शन: कॉलोक() 'नए क्षेत्र में एक सूचक लौटाएगा और सभी बाइट्स को शून्य पर सेट करेगा।

मेमोरी आवंटन फ़ंक्शन: realloc() एक सूचक (संभवतः नए) क्षेत्र में एक सूचक लौटाएगा और पुराने क्षेत्र से बाइट कॉपी करेगा। नए क्षेत्र 'नए' का अनुरोध लंबाई

स्मृति आवंटन समारोह malloc नया क्षेत्र के सूचक वापस आ जाएगी लेकिन

0

मानों वापसी किया जा रहा है किसी भी विशिष्ट मूल्य बाइट्स सेट नहीं होगा सभी 0 (शून्य) हैं।

लेकिन इसकी गारंटी नहीं है। ऐसा इसलिए है क्योंकि आप बस अपना प्रोग्राम चला रहे हैं। यदि आप malloc, यादृच्छिक भरें, और बहुत कुछ मुक्त करते हैं, तो आप पहले से मुक्त स्मृति को पुन: उपयोग कर रहे हैं, इस पर ध्यान देना शुरू कर देंगे, इसलिए आप अपने मॉलॉक्स में गैर-शून्य भाग प्राप्त करना शुरू कर देंगे।

0

हाँ आप सही हैं malloc() शून्य-प्रारंभिक मान नहीं है। यह मनमाने ढंग से ढेर से आवंटित करने के लिए बताई गई स्मृति की मात्रा खींचता है, जिसका अनिवार्य रूप से मतलब है कि पहले से ही कुछ भी संग्रहीत किया जा सकता है। इसलिए आपको केवल malloc() का उपयोग करना चाहिए, जहां आप निश्चित हैं, कि आप इसे एक मान पर सेट करने जा रहे हैं। यदि आप बॉक्स के ठीक से इसके साथ अंकगणित करने जा रहे हैं तो आपको कुछ ख़राब परिणाम मिल सकते हैं (मैंने पहले से ही कई बार व्यक्तिगत अनुभव किया है; आपके पास कभी-कभी पागल आउटपुट के साथ कार्यात्मक कोड होने वाला है)।

तो ऐसी चीजें सेट करें जिन्हें आप स्मृति के साथ शून्य पर शून्य पर सेट नहीं कर रहे हैं()। या मेरी सलाह calloc() का उपयोग करना है। मॉलोक के अलावा, कॉलोक शून्य-प्रारंभिक मान करता है। और जहां तक ​​मैं malloc() और memset() के संयोजन से तेज़ी से जानता हूं, दूसरी ओर मॉलोक अकेले कॉलोक से तेज है। इसलिए आपको स्मृति में स्मृति रखने के द्वारा जारी किए गए सबसे तेज़ संस्करण को खोजने का प्रयास करें।

यहां इस पोस्ट को भी देखें: MPI matrix-vector-multiplication returns sometimes correct sometimes weird values। सवाल एक अलग था, लेकिन कारण एक ही था।

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