c内存管理
Malloc
void* malloc(size_t size)
- 在堆中分配一个长度为size字节的连续空间,返回一个指向所分配的连续存储域的起始地址的指针
void*(可以转换为任何其它类型的指针)。 - 分配的内存未初始化,它们的值是未知的。
- 当函数未能成功分配存储空间时(如内存不足)则返回一个
NULL指针。
uint16_t *p = (uin16_t *)malloc(sizeof(uint16_t));
if (NULL == p)
{
printf("malloc error\r\n");
} else
{
memset(p, 0, n * sizeof(uint16_t)); // 内存的值未知, 需要初始化为0
}
calloc
void *calloc(int num, int size)
- 分配 num 个长度为 size 的连续空间,并将每一个字节都
初始化为 0
realloc
void *realloc(void *address, int newsize);
重新分配内存,把内存扩展到 newsize。- 从堆上当前内存段后面的字节中获得更多的内存空间,如果能够满足,则返回原指针;
- 如果后面的空闲字节不够,那么就使用堆上第一个能够满足这一要求的内存块,将目前的数据复制到新的位置,而将原来的数据块释放掉。
- 如果内存不足,重新申请空间失败,则返回NULL。
- 此时原来指针仍然有效,
memcpy
memcpy(void *dst, void *src, size_t n)
- 从源内存区域复制数据到目标内存区域。
memmove
memcpy(void *dst, void *src, size_t n)
功能和 memcpy 相似, 但它可以处理dst和src重叠的内存区域。
free
void free(void *address);
- 调用free释放内存后,不能再访问被释放的内存空间, 此时的指针变成
悬空指针, 所以最好手动赋值NULL 不能两次释放相同的指针。因为释放内存空间后,该空间就交给了内存分配子程序,再次释放内存空间会导致错误。- 必须提供内存的
起始地址,不能够提供部分地址,释放内存中的一部分是不允许的。 - malloc和free成对使用, 避免
内存泄漏
C++内存管理
new
- 调用
malloc申请并分配内存。 - 调用
构造函数, 初始化相应类型的对象,并返回首地址。
- new运算符会抛出
std::bad_alloc异常,如果加入nothrow,则不抛出异常,而是返回nullptr。
delete
- 调用
析构函数 - 释放内存(
free)
new[]/delete[]
初始化或者释放对象数组
按照对象的个数,分别调用构造函数和析构函数
unique_ptr
- 拥有对象独有所有权语义的智能指针
- unique_ptr 不共享它的指针。它无法复制到其他 unique_ptr,只能
移动unique_ptr。 - 移动后, 内存资源所有权将转移到另一unique_ptr,并且原始 unique_ptr 不再拥有此资源。
unique_ptr<int> pInt(new int(8));
unique_ptr<int> pInt2 = std::move(pInt); // 转移所有权
//cout << *pInt << endl; // 出错,pInt为空
cout << *pInt2 << endl;
shared_ptr
- 拥有共享对象所有权语义的智能指针
- 记录对象被引用的次数,当引用次数为 0 的时候,也就是最后一个指向该对象的共享指针析构的时候,共享指针的析构函数就把指向的内存区域释放掉。
- 它所指向的资源具有共享性,即多个shared_ptr可以指向同一份资源,并在内部使用引用计数机制来实现这一点。
weak_ptr
管理对象的弱引用
OC内存管理
引用计数
alloc/retain/copy引用计数+1release引用计数 -1autorelease出了autoreleasepool(自动释放池))后, 引用计数再 -1- 凡是使用了alloc、retain或者copy让内存的引⽤用计数增加了,就需要使用release或者autorelease让内存的引用计数减少。需要
一一对应。 - 当引用计数降为0之后,不应该再使用这块内存空间;
dealloc
当引用计数减到0的时候,系统自发调用dealloc方法释放内存。
ARC
- 自动引用计数,
编译器帮我们管理对象的retainCount值 - 当开启ARC后, 上述手动改变引用计数的方法就无法使用了
- ARC是
编译器特性,编译器在编译的时候,会在合适的位置,自动插入内存管理的代码
Swift内存管理
Swift无法使用MRC,只支持ARC
strong
默认定义的对象全是强引用,引用计数+1
weak
- 定义弱引用, 不会改变对象的引用计数
- 弱引用变量必须是可选类型的
var,因为对象销毁后,ARC会自动将弱引用设置为nil。
weak var p: Person? = Person()
unowned
- 定义无主引用, 不会改变对象的引用计数
- 对象销毁后仍然存储着实例的内存地址,不会自动设置
nil - 对象销毁后访问无主引用,会产生运行时错误(野指针)。