一、内存分配方式 在 C++ 中,内存分成 5 个区:堆、栈、自由存储区、全局/静态存储区和常量存储区 1、栈 执行函数时,局部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元被自动释放。 栈内存分配运算内置于处理器的指令集中,效率很高,但是分配的内存容量有限。 2、堆 由new分配的内存块,编译器不去管它们 ..

C++ 基础 -- 内存管理

本贴最后更新于 850 天前,其中的信息可能已经斗转星移

一、内存分配方式

二、区分堆、栈

void f() {int* p = new int[8];}

如上代码就包含了堆与栈,先 new 出来一块堆内存,指针 p 指向一块栈内存。
表示:在栈内存中存放了一个指向一块堆内存的指针 p。

b012f00ebeb94b318fb12530a778a096.png

程序经过编译、链接、生成执行程序后,堆和栈的起始地址就已经确定了(具体说,是通过“连接程序”),在一个具有反向增长的栈的 CPU 上,数据空间可表示如下:
99b2665e2c384a6c8378ee94e97eb69e.png
在内存中,“堆”和“栈”共用全部的自由空间,只不过各自的起始地址和增长方向不同,它们之间并没有一个固定的界限,如果在运行时,“堆”和 “栈”增长到发生了相互覆盖时,称为“栈堆冲突”,系统肯定垮台。由于开销方面的原因,各种编译在实现中都没有考虑解决这个问题,只有靠设计者自己解决,比如增加内存等。

三、控制内存分配

 1、 内存分配未成功,却使用了它。

新手没有意识到内存分配会不成功。常用解决办法是,在使用内存之前检查指针是否为NULL。
如果指针p是函数的参数,那么在函数的入口处用assert(p!=NULL)进行检查。
如果是用malloc来申请内存,应该用if(p==NULL) 或if(p!=NULL)进行防错处理。

 2、内存分配虽然成功,但是尚未初始化就引用它。

犯这种错误主要有两个起因:一是没有初始化的观念;二是误以为内存的缺省初值全为零,导致引用初值错误(例如数组)。
内存的缺省初值究竟是什么并没有统一的标准,尽管有些时候为零值,我们宁可信其无不可信其有。
所以无论用何种方式创建数组,都别忘了赋初值,即便是赋零值也不可省略,不要嫌麻烦。

 3、内存分配成功并且已经初始化,但操作越过了内存的边界。

例如在使用数组时经常发生下标“多1”或者“少1”的操作。特别是在for循环语句中,循环次数很容易搞错,导致数组操作越界。

 4、忘记了释放内存,造成内存泄露。

含有这种错误的函数每被调用一次就丢失一块内存。刚开始时系统的内存充足,你看不到错误。
终有一次程序突然死掉,系统出现提示:内存耗尽。
动态内存的申请与释放必须配对,程序中malloc与free的使用次数一定要相同,否则肯定有错误(new/delete同理)。

二、区分堆、栈

void f() {int* p = new int[8];}

如上代码就包含了堆与栈,先 new 出来一块堆内存,指针 p 指向一块栈内存。
表示:在栈内存中存放了一个指向一块堆内存的指针 p。

b012f00ebeb94b318fb12530a778a096.png

程序经过编译、链接、生成执行程序后,堆和栈的起始地址就已经确定了(具体说,是通过“连接程序”),在一个具有反向增长的栈的 CPU 上,数据空间可表示如下:
99b2665e2c384a6c8378ee94e97eb69e.png
在内存中,“堆”和“栈”共用全部的自由空间,只不过各自的起始地址和增长方向不同,它们之间并没有一个固定的界限,如果在运行时,“堆”和 “栈”增长到发生了相互覆盖时,称为“栈堆冲突”,系统肯定垮台。由于开销方面的原因,各种编译在实现中都没有考虑解决这个问题,只有靠设计者自己解决,比如增加内存等。

三、控制内存分配

 1、 内存分配未成功,却使用了它。

新手没有意识到内存分配会不成功。常用解决办法是,在使用内存之前检查指针是否为NULL。
如果指针p是函数的参数,那么在函数的入口处用assert(p!=NULL)进行检查。
如果是用malloc来申请内存,应该用if(p==NULL) 或if(p!=NULL)进行防错处理。

 2、内存分配虽然成功,但是尚未初始化就引用它。

犯这种错误主要有两个起因:一是没有初始化的观念;二是误以为内存的缺省初值全为零,导致引用初值错误(例如数组)。
内存的缺省初值究竟是什么并没有统一的标准,尽管有些时候为零值,我们宁可信其无不可信其有。
所以无论用何种方式创建数组,都别忘了赋初值,即便是赋零值也不可省略,不要嫌麻烦。

 3、内存分配成功并且已经初始化,但操作越过了内存的边界。

例如在使用数组时经常发生下标“多1”或者“少1”的操作。特别是在for循环语句中,循环次数很容易搞错,导致数组操作越界。

 4、忘记了释放内存,造成内存泄露。

含有这种错误的函数每被调用一次就丢失一块内存。刚开始时系统的内存充足,你看不到错误。
终有一次程序突然死掉,系统出现提示:内存耗尽。
动态内存的申请与释放必须配对,程序中malloc与free的使用次数一定要相同,否则肯定有错误(new/delete同理)。

 5、释放了内存却继续使用它。

  • C++

    C++ 是在 C 语言的基础上开发的一种通用编程语言,应用广泛。C++ 支持多种编程范式,面向对象编程、泛型编程和过程化编程。

    57 引用 • 138 回帖 • 467 关注
  • 内存
    10 引用 • 2 回帖
回帖
请输入回帖内容...