内存分配

来源:互联网 发布:windows中,剪贴板是? 编辑:程序博客网 时间:2024/05/16 13:49

标准C为内存分配定义了三个函数:

1.malloc,它分配的是给定字节大小的内存,所分配的内存的初始值是不确定的;

2.calloc,它分配的是给定对象数量的大小,所分配的空间都初始化为0;

3.realloc,它是增大或者减小先前已分配空间的大小。当大小事增大的时候,系统可能把先前已分配好的空间的数据移到某一个地方,然后再在最后添加额外的空间,此时,所增加的空间的初始值是不确定的。

#include <stdlib.h>

void  *malloc(sizet_t  size);

void  *calloc(size_t  nobj, size_t size);

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

三个函数的返回值是:如果成功则返回一个非空指针,错误则返回NULL

void  *free(void *ptr);

因为这三个分配空间的函数返回的是一个通用的void *指针,如果我们#include <stdlib.h>(即包含了stdlib.h头文件来获得函数的原型),那么我们没必要强制转换由这三个函数返回的指针到我们所赋值的不同的指针类型。

free函数的作用是释放由指针ptr所指向的内存空间。被释放的空间通常是放回到一个可用的内存池,并且可以供分配内存的函数(malloc, calloc, realloc)分配。

realloc函数可以让我们增大或者减小先前已分配的内存空间。(通常的使用情况是增大一个内存空间)。例如,我们为一个数组分配了一个512个元素的空间,而我们在程序运行的时候发现我们所需要的内存空间超过512个元素的内存空间,那么我们就可以调用realloc函数。如果原来分配的内存空间之后还有超过要求增大的内存空间,那么当调用realloc时系统就不用移动任何东西;它仅仅是在原来分配的空间之后分配额外的空间,然后返回的还是我们所传给realloc函数的指针。但是如果原来分配的空间之后已没有空间,那么realloc函数就分配另一块足够大的内存区域,把原来含有512个元素的数组复制到新的内存区域,释放(free)原来的内存区域,然后返回一个指向新的内存区域的指针。因为原来的内存空间有可能被移动,所以我们不应该有任何指向它的指针。

注意到realloc函数的最后一个参数是新的内存区域的大小,而不是新的内存空间与原来内存空间相差的大小。有一个特殊的情况就是当ptr指针是NULL指针时,realloc函数的作用和malloc函数一样是分配newsize大小的内存空间。

这些分配内存的函数通常是通过sbrk系统调用实现的。这个系统调用是扩展(或者收缩)进程的堆。

尽管sbrk函数可以扩展或者收缩进程的内存空间,但是大部分版本的malloc和free函数从来不会减小进程的内存空间。我们释放的内存空间可供后续的分配使用,但是已被释放的空间通常不会返回给内核,而是保存在内存分配池(the malloc pool)。

意识到实际分配的内存空间是多于要求分配的是很重要的,多出的额外空间是用来保存记录用的--记录的是所分配块的大小,指向下一个分配块的指针,等类似的东西。这意味着如果对超过所分配大小内存空间进行写操作的话就有可能覆盖掉后一个块的记录保存信息。这种类型的错误通常是致命的,但是很难发现,因为这种错误不到最后可能都不会出现。当然,对分配的区域之前的部分进行写操作也有可能盖写记录块。

对一个动态分配的内存缓冲区开始之前或者结束之后的单元进行写操作不仅仅是破坏记录保存信息。动态分配缓存区之前和之后内存区域可能是为其他动态分配的对象所用的。这些对象与糟糕的代码没有直接的联系,所以非常难以发现错误的源头。

另一个致命的可能错误是释放一个已经释放的块和释放一个并不是由三个内存分配函数获得的指针。如果一个进程 调用malloc函数分配了内存,而忘记了调用free函数释放掉,那么它的内存会不断的增加,这就是内存泄露,如果没有调用free函数来释放不再使用的内存空间,那么进程的地址空间就会缓慢的增加直到没有可以分配的内存空间剩下。此时,因为过度的换页就会导致程序的性能下降。

0 0
原创粉丝点击