malloc()
-
函数原型:linux下:
void *malloc(size_t size);
,windows:void *malloc(unsigned int num_bytes);
size单位是字节,表示申请的空间大小。
返回void *,分配成功则返回未确定类型的指针(可强制类型转换),指向该内存首地址;分配失败则返回NULL。 -
C语言中动态分配内存malloc(),在linux中的实现是,malloc()函数调用库函数
sbrk()
,sbrk()的实质是调用brk()
函数。brk()是一个简单的系统调用,只是简单的改变mm_struct结构体的成员变量brk的值。mm_struct结构体中的成员变量:
start_code 和 end_code 是进程代码段的起始和结束地址、
start_data 和 end_data 是进程数据段的起始和终止地址。
start_stack 是进程堆栈段的起始地址。
start_brk 是进程动态内存分配的起始地址(堆的起始地址)。
brk 是进程动态内存分配当前的终止地址(堆的当前最后地址)。 -
与free()对应,释放不再使用的对象。
-
与C++中内存分配的
new
的区别是,new返回指定类型的指针,并且可以自动计算所需要的大小。// new
int *p;
p = new int;//返回类型为int* ,分配的大小是sizeof(int)
// malloc
int *p;
p = (int *)malloc(sizeof(int));
-
实现:当线程需要使用malloc函数分配内存空间时,该线程会先查看线程的私有变量中是否已经存在有一个分配区,如果存在,尝试对分配区加锁,如果加锁成功就使用这个分配区分配内存。如果失败,该线程就搜索循环链表试图获得一个没有加锁的分配区来分配内存。如果所有的分配区都加锁,那么malloc会开辟一个新的分配区,把该分配区添加到循环链表中并加锁,使用这个分配区进行分配内存操作。在释放操作中,线程同样试图获得待释放内存块所在的分配区的锁,如果该分配区正在被别的线程使用,则需要等待直到其他线程释放该分配区的互斥锁之后才可以进行释放操作。
realloc()
-
函数原型:
void *realloc(void *ptr, unsigned int newsize);
重新分配内存大小。ptr
:原内存地址,newsize:修改后的内存大小。 -
执行逻辑:先判断当前的指针是否有足够的连续空间,如果有,扩大ptr指向的地址,并且返回ptr(原指针),如果空间不够,先按照newsize指定的大小分配空间,将原有数据从头到尾拷贝到新分配的内存区域,而后释放原来ptr所指内存区域(原来的指针是自动释放,不需要使用free),同时返回新分配的内存区域的首地址,即重新分配存储器块的地址。
如果重新分配成功则返回指向被分配内存的指针,否则返回空指针NULL。
如果堆空间不足,函数调用失败,那么可能会造成数据丢失和free失败产生的内存泄漏(用原指针接收分配后的指针的时候,如果分配失败,原指针被赋值为null,则原内存空间无法找到,发生泄漏)。
calloc()
- 函数原型:
void *calloc(int count, int size);
分配指定数量指定大小的内存空间。 - 表示向系统申请分配 count 个长度为 size 一共为 count 乘以 size 个字节长度的连续内存空间,并将每一个字节都初始化为 0。
free()
- 函数原型:
void free(void *ptr);
- 可以释放由 malloc()、calloc()、realloc() 分配的内存空间。
- 调用 free() 后原指针仍然会指向相同的内存空间,但是此时该内存已被释放,不能被使用。
【参考链接】
C语言-内存管理基础