您的位置:首页 > 编程语言 > C语言/C++

malloc,calloc,realloc,memset之间的关系

2017-09-14 11:38 344 查看
阅读下面文章可以同时参考C运行时库(C run-time library)

1.首先要了解的是:

堆栈区(stack):由编译器自动分配与释放,存放函数的参数值,局部变量,临时变量等等,它们获取的方式都是由编译器自动执行的

堆区(heap):一般由程序员分配与释放,基程序员不释放,程序结束时可能由操作系统回收(C/C++没有此等回收机制,Java/C#有),注意它与数据结构中的堆是两回事,分配方式倒是类似于链表。

全局区(静态区)(static):全局变量和静态变量的存储是放在一块儿的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统释放。

文字常量区:常量字符串是放在这里的,程序结束后由系统释放。

程序代码区:存放函数体的二进制代码。

2.malloc()可以从堆上获得指定字节的内存空间

void *malloc(

size_t size

);

(1)形参size为要求分配的字节数。

(2)如果函数执行成功,malloc返回获得内存空间的首地址;如果函数执行失败,那么返回值为NULL。

(3)由于 malloc函数值的类型为void型指针,因此,可以将其值类型转换后赋给任意类型指针,这样就可以通过操作该类型指针来操作从堆上获得的内存空间。

(4)malloc函数分配得到的内存空间是未初始化的。因此,一般在使用该内存空间时,要调用另一个函数memset来将其初始化为全0。

3.memset()将指定的内存空间按字节单位置为指定的字符

void *memset(

void *dest,

int c,

size_t count

);

该函数可以将指定的内存空间按字节单位置为指定的字符c。其中,dest为要清零的内存空间的首地址,c为要设定的值,count为被操作的内存空间的字节长度。如果要用memset清0,变量c实参要为0。

4.calloc函数的功能与malloc函数的功能相似,都是从堆分配内存

void *calloc(

size_t num,

size_t size

);

(1)calloc函数为数组分配存储空间num元素,每个长度size字节。 每个元素初始化为 0。

(2)calloc返回指向分配的空间的指针。 返回值指向的存储空间保证适当对齐任何类型的对象的存储。 若要获取指向一种类型的指针,而不是返回void,应使用类型转换。

5.realloc()可以实现内存分配和内存释放的功能

void *realloc(

void *memblock,

size_t size

);

(1)指针memblock必须为指向堆内存空间的指针,即由malloc函数、calloc函数或realloc函数分配空间的指针。

(2)realloc函数将指针 memblock指向的内存块的大小改变为size字节。如果size小于或等于memblock之前指向的空间大小,那么。保持原有状态不变。如果size大于原来memblock之前指向的空间大小,那么,系统将重新为memblock从堆上分配一块大小为size的内存空间,同时,将原来指向空间的内容依次复制到新的内存空间上,memblock之前指向的空间被释放。relloc函数分配的空间也是未初始化的。

???(3)realloc是从堆上分配内存的,当扩大一块内存空间时, realloc()试图直接从堆上现存的数据后面的那些字节中获得附加的字节,如果能够满足,自然天下太平;可如果数据后面的字节不够的话,问题就出来了,那么就使用堆上第一个有足够大小的自由块,现存的数据然后就被拷贝至新的位置,而老块则放回到堆上。

6.free()

void free(

void *memblock

);

(1)从堆上获得的内存空间在程序结束以后,系统不会将其自动释放,需要程序员来自己管理。一个程序结束时,必须保证所有从堆上获得的内存空间已被安全释放,否则,会导致内存泄露

(2)若释放了无效的指针(malloc/calloc/realloc的指针指向未分配的内存块),可能会影响后续分配请求,并导致错误

注意:

1.有经验的程序员更喜欢使用calloc(),因为这样的话新分配内存的内容就不会有什么问题,调用calloc()肯定会清0,并且可以避免调用memset().

2.进程对动态内存的请求被认为是不紧迫的。例如,当进程的可执行文件被装入时,进程并不一定立即对所有的代码进行访问。类似地,当进程调用malloc() 请求动态内存时,并不意味着进程很快就会访问所有获得的内存。因此一般来说,内核总是尽量推迟给用户态进程动态分配内存。

3.malloc()函数有一个参数,即分配的内存空间的大小,malloc在分配内存的时候会保留一定的空间用来记录分配情况,分配的次数越多,这些记录占用的空间就越多。另外,根据malloc实现策略的不同,malloc每次在分配的时候,可能分配的空间比实际要求的多些,多次分配会导致更多的这种浪费,当然,这些都跟malloc的实现有关;

4.relloc()可以对给定的指针所指的空间进行扩大或者缩小,无论是扩张或者缩小,原有内存中的内容将保持不变。当然,对于缩小,则被缩小的那一部分的内容会丢失。

relloc()并不保证调整后的内存空间和原来的内存空间保持同一内存地址,相反,relloc返回的指针很可能指向一个新地址。所以在代码中,我们必须将relloc的返回值,重新赋值给memblock : memblock =(size_t *) relloc (memblock ,sizeof(size_t )*15);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  c语言