C++ new、delete和动态内存

动态内存=智能指针 +直接管理(new delete)

why使用动态内存?

  1. 程序不知道需要使用多少对象
  2. 不知道所需对象的类型
  3. 需要在多个对象间共享数据

c++ 内存分类:栈区,堆区,全局区(静态区), 常量区,代码区
静态栈,局部变量
动态堆,new malloc

1,c++的四个智能指针:(头文件memory)

auto_ptr 弃用,被unique_ptr代替!
shared_ptr 允许多个指针指向同一个对象。 两个对象相互使用一个
shared_ptr成员变量指向对方,会造成循环引用,使引用计数失效,从而内存泄漏。实现共享式拥有概念。多个智能指针可以指向相同对象,该对象和其相关资源会在“最后一个引用被销毁”时候释放
make_shared函数,是最安全的分配和使用动态内存的方法。

make_shared在动态内存中分配一个对象并初始化,返回指向该对象的shared_ptr。
shared_ptr<int> p=make_shared<int>(0)//指向值为0的int的shared_ptr
auto q(p);//用p来初始化q,两个指向相同对象。。引用计数加一!!!
q.use_count()//计数
auto r=make_shared<int>(43);
r=s;//r原来指向的对象没有引用者,会调用析构函数,销毁对象。释放内存!!!
shared_ptr<int> p1(new int(1024));//shared_ptr用new初始化
p1.reset//释放

unique_ptrr “唯一”拥有其所指对象,同一时刻只能有一个unique_ptr指向给定对象(其他指针想指向这个对象,先release!!!)。避免资源泄露

unique_ptr<int> u1 (new int(1024));//不支持拷贝和赋值
u1=nullptr;//释放u指向的对象,将u置空
u1.reset();//释放u指向的对象
u1.release();//u放弃原指针的控制权,将u置空。返回指针,返回指针,返回指针!!!!
unique_ptr<int> p2(p1.release());//将所有权从p1转移给p2

weak_ptr 解决了循环引用导致的内存泄漏问题。指向shared_ptr所管理的对象,但不增加use_count()。

auto p=make_shared<int>(42);
weak_ptr<int>wq(p);//wq弱共享p。

智能指针的作用:
智能指针的作用是管理一个指针。申请的空间在函数结束时忘记释放,会造成内存泄漏。使用智能指针可以避免。智能指针是一个类,当超出了类的作用域,类会自动调用析构函数来释放资源。

2,new,new[]和malloc

不同之处:
当new[]中的数组元素基本类型时,通过delete和delete[]都可以释放数组空间;
当new[]中的数组元素是自定义类型时,只能通过delete[]释放数组空间。
当数组中的袁术是自定义类型时,delete在释放空间时只会调用数组中首个元素的析构函数,
而delete[]在释放空间时会调用数组中所有元素的析构函数。
new/delete malloc/free
关键字,可重载 库函数
调用构造/析构函数。对象+内存 内存
返回指向对象的指针 返回void*,还需强转
按照数据类型自动分配内存 申请时指定大小,可以realloc扩容。
分配失败返回bad_malloc,尽量try catch 分配失败返回NULL
malloc和new区别:
1.new/delete是C++关键字,需要编译器支持。new会调用构造函数,不能指定内存大小,返回的指针不需强转。除内部数据类型外,还支持动态对象。对象+内存,返回指向对象的指针。new失败返回badallloc异常,可以nothrow不抛出异常
2.malloc需要指定申请内存的大小,返回的指针需强转。。malloc/free是库函数,需要头文件支持。仅支持内部数据类型。内存。返回void*

int *arr=int*malloc(sizeof(int)*n)
free(arr);
//如果new失败,返回一个bad_alloc类型的异常
int *pi=new int(1024);//pi指向对象的值为1024
string *ps=new string//string初始化为空了
auto p1=new auto(obj);//obj是int,那么p1就是int*了
const int *p=new const int(1024);
delete p;//销毁对象 释放内存。所以p必须是对象或空指针
动态数组(不建议用,还是建议用标准容器)
int *p=new int[40];//表示有40个int
int *p1=new int[40]()//初始化为0了
delete []p;//逆序先销毁最后一个,,,直到第一个元素
智能指针unique_ptr可以管理动态数组new[]
unique_ptr<int[]> p(new int[10]);
p.release();//自动调用delete[]
allocator类
allocator<string>alloc;
auto const p=alloc.allocate(n);//分配n个未初始化的string
alloc.deallocate(p,n)//释放p指向的那块内存
alloc.desdoy(p);//调用析构函数,销毁p指向的对象

auto q=p;//q指向最后一个元素位置
alloc.construct(q++,"hello");//初始化构造的对象
while(q!=p)
    alloc.destroy(--q);//销毁对象(必须是先构造的元素)

3,malloc原理。brk和mmap系统调用?

为了减少内存碎片和系统调用的开销,malloc采用内存池的方式,先申请大块内存作为堆区,然后将堆区分为多个内存块(块是内存管理的基本单位),当用户申请内存时,直接从堆区分配一块合适的空闲块。malloc将堆区分成连续的,大小不同的块(已分配块和空闲块),再把用双向链表把空闲块连接起来。
用户申请内存时,malloc便利所有空闲块,再分配大小合适的块。。。(内存合并时,malloc采用边界标记法,根据每个块的前后块是否分配来决定是否合并。)
malloc申请内存时一般用到brk或mmap系统调用。当申请内存小于128k时,会使用系统函数brk在堆区分配。大于128k时,使用mmap在映射区分配。

4,野指针和空悬指针

空悬指针是这样一种指针:它曾经指向一个有效地址,但是现在不再指向有效地址(个人添加,其实就是原来的那块地址不能通过这个指针区访问了)。这通常是因为指针所指的内存单位被释放了并且不再有效了。空悬指针存在并没有什么问题,除非你尝试通过这个指针访问指向的地址空间。不遗留任何悬空指针总是最好的实践方式。

#include <stdlib.h>
void func(){
    char *dp = (char *)malloc(A_CONST);
    free(dp);         //dp变成一个空悬指针
    dp = nullptr;        //dp不再是空悬指针
}

上述例子提醒我们,当free或者delete调用时,除了释放动态申请的内存,还要将相关的指针指向NULL,避免出现空悬指针。

野指针是这样一种指针:它没有被正确的初始化于是指向一个随机的内存地址。存在野指针是一个严重的错误。

野指针:野指针指向了一块随机内存空间,不受程序控制。
如未初始化或者指向一块没有访问权限的内存空间,之后如果对其再解引用的话,就会出现问题。

造成野指针的原因
1、指针变量没有被初始化。任何指针变量刚被创建时不会自动成为NULL指针,它的默认值是随机的,它会乱指一气。
2、指针p被free或者delete之后,没有置为NULL,让人误以为p是个合法的指针。//这是空悬指针
3、指针操作超越了变量的作用范围。这种情况让人防不胜防。

5,内存泄漏

定义:内存泄漏指的是由于疏忽或错误造成了程序未能释放掉不再使用的内存。
内存溢出:使用的内存空间超出了系统分配的
后果:性能不良,内存耗尽
常见类型:
堆内存泄漏:用了malloc、new和realloc。没用free和delete释放
系统资源泄漏:分配给程序使用的资源没有使用相应函数释放,如bitmap\handle\socket.
基类析构函数不是虚函数的话,基类指向子类对象时,不会调用子类的析构函数,造成内存泄漏。
排查:BoundsChecker,定位运行时发生的各种错误
调试运行DEBUG版程序,运用以下技术:CRT(C run-time libraries)、运行时函数调用堆栈、内存泄漏时提示的内存分配序号(集成开发环境OUTPUT窗口),综合分析内存泄漏的原因,排除内存泄漏。
linux工具之检测内存泄漏-valgrind
windows用CRT的库函数检测
mtrace追踪检测malloc。或者 手动添加内存申请和释放的统计功能,查看是否一致来判断泄漏

解决:使用智能指针、初始化为null
内存溢出 out of memory,是指程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;比如申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。

发布了19 篇原创文章 · 获赞 9 · 访问量 2920

猜你喜欢

转载自blog.csdn.net/u013031697/article/details/104824662