2010-01-26 8 views
6

के बाद नई मेमोरी को शून्य कैसे करें प्रारंभ में आवंटित स्मृति को बरकरार रखने के दौरान रीयलोक को कॉल करने के बाद नई मेमोरी को शून्य करने का सबसे अच्छा तरीका क्या है?realloc

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

size_t COLORCOUNT = 4; 

typedef struct rgb_t { 
    int r; 
    int g; 
    int b; 
} rgb_t; 

rgb_t** colors; 

void addColor(size_t i, int r, int g, int b) { 
    rgb_t* color; 
    if (i >= COLORCOUNT) { 
     // new memory wont be NULL 
     colors = realloc(colors, sizeof(rgb_t*) * i); 
     //something messy like this... 
     //memset(colors[COLORCOUNT-1],0 ,sizeof(rgb_t*) * (i - COLORCOUNT - 1)); 

     // ...or just do this (EDIT) 
     for (j=COLORCOUNT; j<i; j++) { 
      colors[j] = NULL; 
     } 

     COLORCOUNT = i; 
    } 

    color = malloc(sizeof(rgb_t)); 
    color->r = r; 
    color->g = g; 
    color->b = b; 

    colors[i] = color; 
} 

void freeColors() { 
    size_t i; 
    for (i=0; i<COLORCOUNT; i++) { 
     printf("%x\n", colors[i]); 
     // can't do this if memory isn't NULL 
     // if (colors[i]) 
     // free(colors[i]); 

    } 
} 


int main() { 
    colors = malloc(sizeof(rgb_t*) * COLORCOUNT); 
    memset(colors,0,sizeof(rgb_t*) * COLORCOUNT); 
    addColor(0, 255, 0, 0); 
    addColor(3, 255, 255, 0); 
    addColor(7, 0, 255, 0); 


    freeColors(); 
    getchar(); 
} 
+0

यह * बहुत * खराब प्रदर्शन होता है जब रंगों की सूची के अंत में एक रंग जोड़ा जाता है, सामान्य कॉलिंग पैटर्न। आप पुनः आवंटन से पहले एक समय में केवल एक तत्व जोड़ देंगे। कम से कम आवंटित करने पर विचार करें (i + 1, COLORCOUNT * 2)। –

+0

यह समस्या का वर्णन करने के लिए सिर्फ एक उदाहरण है। वास्तविक स्रोत एक हैश टेबल है जो प्राइम नंबर आईआईआरसी –

उत्तर

4

की तरह एक आवरण लिख सकता है शायद memset ऐसा करने के लिए कोई जरूरत नहीं है: आप बाद में कुछ वैध के साथ सेट करने से पहले colors[k] का उपयोग नहीं किया जा सकता है। उदाहरण के लिए, आपका कोड colors[i] को नए आवंटित color पॉइंटर पर सेट करता है, इसलिए आपको colors[i] से NULL पर सेट करने की आवश्यकता नहीं थी।

लेकिन, अगर आप "इसे शून्य करना चाहते हैं तो सब कुछ अच्छा है", या वास्तव में NULL होने के लिए नए पॉइंटर्स की आवश्यकता है: सी मानक गारंटी नहीं देता है कि सभी बिट्स-शून्य शून्य सूचक स्थिर है (यानी, NULL), इसलिए memset() वैसे भी सही समाधान नहीं है।

केवल पोर्टेबल बात आप कर सकते हैं एक पाश में NULL करने के लिए प्रत्येक सूचक स्थापित करने के लिए है:

size_t k; 
for (k=COLORCOUNT; k < i+1; ++k) /* see below for why i+1 */ 
    colors[k] = NULL; 

आपका प्राथमिक समस्या अपने realloc() कॉल गलत है। realloc() आकार की स्मृति में एक सूचक लौटाता है, यह (आवश्यक रूप से) इसे जगह में आकार बदलता नहीं है।

तो, आपको क्या करना चाहिए:

/* i+1 because you later assign to colors[i] */ 
rgb_t **tmp = realloc(colors, (i+1) * sizeof *tmp); 
if (tmp != NULL) { 
    /* realloc succeeded, can't use colors anymore */ 
    colors = tmp; 
} else { 
    /* realloc failed, colors is still valid */ 
} 

तुम सच में पता है कि memset() कॉल किया जाना चाहिए, तो आप स्मृति colors+COLORCOUNT पर शुरू शून्य पर सेट करने की जरूरत है, और शून्य करने के लिए i+1-COLORCOUNT सदस्यों सेट करना चाहते हैं:

memset(colors+COLORCOUNT, 0, (i+1-COLORCOUNT) * sizeof *colors); 

लेकिन जैसा कि मैंने ऊपर कहा, सभी बाइट्स शून्य, एक NULL सूचक होने की गारंटी नहीं है तो अपने memset() वैसे भी बेकार है। यदि आप NULL पॉइंटर्स चाहते हैं तो आपको लूप का उपयोग करना होगा।

+0

धन्यवाद - रीयलोक त्रुटि परीक्षण को जल्दी लिखते समय एक निरीक्षण था, लेकिन मुझे नहीं पता था कि सभी बाइट शून्य शून्य के सभी सरणी सदस्यों को मानक के अनुसार गारंटी नहीं देते हैं। –

3

सबसे पहले, realloc विफल हो सकता है, तो आपको NULL की जांच करने की आवश्यकता है। दूसरा, स्मृति को शून्य करने का कोई बेहतर तरीका नहीं है: पुराने बफर के अंत से बड़े बफर के अंत तक बस याद रखें।

+0

द्वारा आकार दिया गया है, मेरी टिप्पणी सेक्शन अनुभाग "msvcr90d.dll! Memset (unsigned char * dst = 0x00000000, unsigned char value = '', हस्ताक्षरित लंबी गिनती = 2553828) लाइन के साथ दृश्य स्टूडियो को क्रैश करता है 103 \t एएसएम "। क्या मैं सिर्फ 1 से दूर हूं? –

+1

ऐसा लगता है कि आप उस स्थान के सूचक के बजाय रंगों [COLORCOUNT-1] पर मूल्य को पारित कर रहे हैं। – atk

+0

रीयलोक जगह में फिर से स्थानांतरित करने में सक्षम नहीं हो सकता है और एक नया सूचक वापस कर देगा। यदि आप शून्य नहीं हैं तो आपको इसे जांचना चाहिए और नए मान के साथ रंग अपडेट करना चाहिए। कोड एक असफल हो सकता है। दूसरा कारण यह हो सकता है कि realloc अधिक स्मृति आवंटित नहीं कर सका (यह आपको यह बताने के लिए NULL लौटा, लेकिन आप इसे छोड़ दें)। – Draemon

1

अपना खुद का फ़ंक्शन लिखें, reallocz कहें, जो वर्तमान आकार को पैरामीटर के रूप में स्वीकार करता है, और आपके लिए realloc और memset पर कॉल करता है। यह वास्तव में आपके पास पहले से कहीं ज्यादा बेहतर नहीं होगा ... यह सी है, आखिरकार।

6

इसे सामान्य पैटर्न के रूप में हल करने का कोई तरीका नहीं है। इसका कारण यह है कि बफर का कौन सा हिस्सा नया है, आपको यह जानने की जरूरत है कि पुराना बफर कितना समय था। सी में यह निर्धारित करना संभव नहीं है और इसलिए एक सामान्य समाधान को रोकता है।

हालांकि आप ऐसा

void* realloc_zero(void* pBuffer, size_t oldSize, size_t newSize) { 
    void* pNew = realloc(pBuffer, newSize); 
    if (newSize > oldSize && pNew) { 
    size_t diff = newSize - oldSize; 
    void* pStart = ((char*)pNew) + oldSize; 
    memset(pStart, 0, diff); 
    } 
    return pNew; 
} 
संबंधित मुद्दे