内存分配有三种方式:
1.从静态存储区分配,生命周期随程序的结束而结束,比如说全局变量,static变量
2.从栈空间分配,函数调用完成后被自动释放
3.从对空间分配,即动态内存开辟,比如malloc,calloc,realloc
malloc、calloc、realloc和free
【1】malloc
函数原型 :
void* malloc(size_t size)
这个函数向内存申请一块连续的可用空间,并返回指向这块空间的指针
- 如果开辟成功,返回指向开辟空间的指针
- 如果开辟失败,返回一个NULL指针
- 返回值为void* ,所以malloc函数并不知道开辟空间的类型,再使用时由用户决定
- 如果参数size为0,malloc的行为是标准未定义的,取决于编译器。
- free前后不会修改指针的指向,指针地址仍然不变,free后目标指针会变为野指针,因此最好设置为NULL。
- malloc申请空间完成后,可以使用memset进行初始化。
【2】calloc
函数原型:
void* calloc(size_t num,size_t size)
与函数 malloc 的区别只在于 calloc 会在返回地址之前把申请的空间的每个字节初始化为全0
【3】reallc
函数原型:
void* realloc(void* ptr,size_t size)
- ptr是要调整的内存地址
- size是调整之后的新大小
- 返回值是调整之后的内存的起始地址
- 函数在调整原来的内存空间大小的基础上,还将原来的内存中的数据移动到新的空间中去。
realloc可以对给定的指针所指向的空间进行调整扩大或者缩小,无论是扩张还缩小,原有内存的内容不变,对于缩小,则被缩小的的那部分可能会存在内容丢失问题,realloc并不保证调整后的内存空间和原来的空间地址相同,相反,reallc可能会返回一个新的地址。
realloc是从堆上分配内存的,当扩大一块内存时,堆上的空间足够大时,可以满足扩大要求,那么它就在原来的基础上,扩大字节数,返回原来内存空间的地址;当不满足扩大要求时,则realloc在堆上找到一个有足够大空间的新空间,将原来的数据拷贝至新的位置,并且返回新地址,即realloc可能发生数据迁移。
【4】常见的内存错误
1.如果分配未成功,但是我们使用了
如果是函数传参的问题,则在函数内部使用了assert断言;如果是用malloc等申请内存,应该使用if语句进行判断
2.内存分配成功,但是没有初始化
3、忘记释放内存,会造成内存泄露(动态内存开辟必须和释放配对使用)
【5】几点建议
1 用 malloc 等申请内存之后,应该立即检查指针值是否为 NULL。防止使用指针值为 NULL 的内存。
2 不要忘记为数组和动态内存赋初值。防止将未被初始化的内存作为右值使用。
3 避免数组或指针的下标越界,特别要当心发生“多 1”或者“少 1” 操作。
4 动态内存的申请与释放必须配对,防止内存泄漏。
5 用 free 释放了内存之后,立即将指针设置为 NULL,防止产生“野指针