關於realloc的調整記憶體方式

來源:互聯網
上載者:User

PROTOTYPE:

void * realloc ( void * ptr, size_t new_size );

關於realloc的行為方式,結合源碼總結為:

1. realloc失敗的時候,返回NULL;


2. realloc失敗的時候,原來的記憶體不改變,也就是不free或不move,(這個地方很容易出錯);


3. 假如原來的記憶體後面還有足夠多剩餘記憶體的話,realloc的記憶體=原來的記憶體+剩餘記憶體,realloc還是返回原來記憶體的地址; 假如原來的記憶體後面沒有足夠多剩餘記憶體的話,realloc將申請新的記憶體,然後把原來的記憶體資料拷貝到新記憶體裡,原來的記憶體將被free掉,realloc返回新記憶體的地址;

4. 如果size為0,效果等同於free();

5. 傳遞給realloc的指標可以為空白,等同於malloc;

6. 傳遞給realloc的指標必須是先前通過malloc(), calloc(), 或realloc()分配的。

source code在此,對號入座:

/* realloc.c - C standard library routine.   Copyright (c) 1989, 1993  Michael J. Haertel   You may redistribute this library under the terms of the   GNU Library General Public License (version 2 or any later   version) as published by the Free Software Foundation.   THIS SOFTWARE IS PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED   WARRANTY.  IN PARTICULAR, THE AUTHOR MAKES NO REPRESENTATION OR   WARRANTY OF ANY KIND CONCERNING THE MERCHANTABILITY OF THIS   SOFTWARE OR ITS FITNESS FOR ANY PARTICULAR PURPOSE. */#include <limits.h>#include <stddef.h>#include <stdlib.h>#include <string.h>#include "malloc.h"#ifdef __ELF__#pragma weak realloc = __libc_realloc#endif#define MIN(A, B) ((A) < (B) ? (A) : (B))/* Resize the given region to the new size, returning a pointer   to the (possibly moved) region.  This is optimized for speed;   some benchmarks seem to indicate that greater compactness is   achieved by unconditionally allocating and copying to a   new region. */void *__libc_realloc (void *ptr, size_t size){    void *result, *previous;    int block, blocks, type;    int oldlimit;    if (!ptr)        return __libc_malloc(size);    if (!size) {        __libc_free(ptr);        return __libc_malloc(0);    }    block = BLOCK(ptr);    switch (type = _heapinfo[block].busy.type) {    case 0:        /* Maybe reallocate a large block to a small fragment. */        if (size <= BLOCKSIZE / 2) {            if ((result = __libc_malloc(size)) != NULL) {                    memcpy(result, ptr, size);#if 1                    __libc_free(ptr);#else                    _free_internal(ptr);#endif            }            return result;        }        /* The new size is a large allocation as well; see if           we can hold it in place. */        blocks = BLOCKIFY(size);        if (blocks < _heapinfo[block].busy.info.size) {            /* The new size is smaller; return excess memory               to the free list. */            _heapinfo[block + blocks].busy.type = 0;            _heapinfo[block + blocks].busy.info.size                = _heapinfo[block].busy.info.size - blocks;            _heapinfo[block].busy.info.size = blocks;#if 1            __libc_free(ADDRESS(block + blocks));#else            _free_internal(ADDRESS(block + blocks));#endif            return ptr;        } else if (blocks == _heapinfo[block].busy.info.size)            /* No size change necessary. */            return ptr;        else {            /* Won't fit, so allocate a new region that will.  Free               the old region first in case there is sufficient adjacent               free space to grow without moving. */            blocks = _heapinfo[block].busy.info.size;            /* Prevent free from actually returning memory to the system. */            oldlimit = _heaplimit;            _heaplimit = 0;#if 1            __libc_free(ptr);#else            _free_internal(ptr);#endif            _heaplimit = oldlimit;            result = __libc_malloc(size);            if (!result) {                /* Now we're really in trouble.  We have to unfree                   the thing we just freed.  Unfortunately it might                   have been coalesced with its neighbors. */                if (_heapindex == block)                    __libc_malloc(blocks * BLOCKSIZE);                else {                    previous = malloc((block - _heapindex) * BLOCKSIZE);                    __libc_malloc(blocks * BLOCKSIZE);#if 1                    __libc_free(previous);#else                    _free_internal(previous);#endif                }                            return NULL;            }            if (ptr != result)                memmove(result, ptr, blocks * BLOCKSIZE);            return result;        }        break;    default:        /* Old size is a fragment; type is logarithm to base two of           the fragment size. */        if ((size > 1 << (type - 1)) && (size <= 1 << type))            /* New size is the same kind of fragment. */            return ptr;        else {            /* New size is different; allocate a new space, and copy               the lesser of the new size and the old. */            result = __libc_malloc(size);            if (!result)                return NULL;            memcpy(result, ptr, MIN(size, 1 << type));            __libc_free(ptr);            return result;        }        break;    }}

上面函數流程圖如下:

注意事項:
1. ptr必須為NULL,或者為malloc,realloc或者calloc的傳回值,否則發生realloc invalid pointer錯誤;2. new_size如果小於old_size,只有new_size大小的資料會被儲存,可能會發生資料丟失,謹慎使用;3. 如果new_size大於old_size,可能會分配一塊新的記憶體,這時候ptr指向的記憶體會被釋放,ptr成為野指標,再訪問的時候會發生錯誤;4. 最後不要將返回結果再賦值給ptr,即ptr=realloc(ptr,new_size)是不建議使用的,因為如果記憶體配置失敗,ptr會變為NULL,如果之前沒有將ptr所在地址賦給其他值的話,會發生無法訪問舊記憶體空間的情況,所以建議使用temp=realloc(ptr,new_size)。

流程圖及注意事項來源於:http://www.cnblogs.com/ladd/archive/2012/06/30/2571420.html

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.