栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

【C++碎碎念】内存

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

【C++碎碎念】内存

目录

一、C++的内存管理

1、内存的分配方式 

2、简述一下堆和栈的区别 

3、常见的内存错误及解决方法 

4、什么是内存泄漏,有什么解决办法

二、一个程序都有什么部分,分别的作用是什么,程序启动的过程是什么,怎么判断数据是分配到堆上还是栈上?

 1、一个程序有哪些部分?

2、程序启动的过程是什么?

3、怎么判断数据分配到栈上还是在堆上呢?

一、C++的内存管理

1、内存的分配方式 

        在C++中,内存分成五个区,他们分别是堆、栈、自由存储区、全局/静态存储区和常量存储区。

        栈 在执行函数时,函数内部变量的存储单元都可以在栈上创建,函数执行结束时这些存储单元自动被释放;

        堆 由malloc和free申请和释放的内存;

        自由存储区 由new和delete申请和释放的内存;

        全局/静态存储区 都在同一块静态存储区

        常量存储区 这块比较特殊,不需要修改

2、简述一下堆和栈的区别 

区别:

        1、堆栈空间分配不同  栈由操作系统自动分配和释放,存放函数的参数值、局部变量值等;而堆由程序员自动分配和释放。

        2、堆栈缓存方式不同  栈使用的是一级缓存,他们通常都是在被调用时处于存储空间,调用完毕立即释放;堆存放在二级缓存中,速度要慢些。

        3、堆栈数据结构不同  堆类似于数组结构,栈类似于栈结构,先进后出。

3、常见的内存错误及解决方法 

(1)内存未分配成功,却使用了它

        解决:定义指针时先初始化为NULL。在使用指针之前先初始化为NULL,如果是malloc或者new分配的内存,一定要先检查if(p!=NULL)或者if(p==NULL)进行检查。

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

        解决:很多时候我们总以为分配内存后操作系统系统会给他赋初值,但是很多时候并不是这样的,为了保险起见,我们在分配内存的时候最好给它赋上初值。

(3)内存分配成功并且已经赋初值,但是操作越过了内存边界

        解决:避免数字或者指针的下标越界,特别要当心发生“多1”或者“少1”的操作,尤其是在for循环时,特别容易进行多1的操作,这块就得提醒我们小心点了。

(4)忘记释放内存,造成内存泄漏

       解决: 动态内存的申请和释放必须配对,防止内存泄漏。但有些时候我们只进行了malloc或者new开辟了内存空间,并没有free或者delete进行释放,也没有发生什么故障,这是因为内存比较充足,但每调用一次函数,就减少一块内存,但毕竟内存是有限的,如果无休止的调用下去总会出现内存不够用的情况,直到程序死掉。

(5)释放了内存却继续使用它

        解决:使用free或者delete释放了内存后应立即将指针设置为NULL,防止“野指针”。

4、什么是内存泄漏,有什么解决办法

内存泄漏:简单的说就是申请了一块内存空间,使用完毕没有释放掉;

比如说:(1)new和malloc申请资源使用后,没有用delete和free释放;

        (2)子类继承父类时,父类的析构函数不是虚析构;

        (3)Windows句柄资源使用后没有释放。

解决办法:

        第一:良好的编码习惯,使用了内存分配的函数,一旦使用完毕就立马释放掉

        第二:子类继承父类时,父类的析构函数修改成虚析构函数;

        第三:使用智能指针;

        第四:一些常见的工具帮助检测,如ccmalloc、Dmalloc、Leaky等等。

二、一个程序都有什么部分,分别的作用是什么,程序启动的过程是什么,怎么判断数据是分配到堆上还是栈上?

 1、一个程序有哪些部分?

从上图可以看出,从低地址到高地址,一个程序由代码段、数据段、BSS段组成

1、数据段:存放程序中已经初始化的全局变量和静态变量的一块区域

2、代码段:存放程序执行代码的一段内存区域,只读。代码段的头部还会包含一些只读的常数变量

3、BSS段:存放程序中未初始化或者初始化为0的全局变量和静态变量的一块区域,可读写的,在程序执行之前BSS段会自动清0;

4、可执行程序在运行时又会多出两个区域:堆区和栈区

堆区heap:动态申请内存,堆从低地址向高地址增长;

栈区stack:存储局部变量、函数参数值,栈从高地址到低地址增长,是一块连续的空间。

5、文件映射区:位于堆和栈之间。

2、程序启动的过程是什么?

(1)操作系统首先创建相应的进程并分配私有的进程空间,然后操作系统的加载器负责把可执行文件的数据段和代码段映射到进程的虚拟内存空间中;

(2)加载器读入可执行程序的导入符号表,根据这些符号表可以查找出该可执行程序的所有依赖的动态链接库;

(3)加载器针对该程序的每一个动态连接库调用LoadLibrary;

(4)初始化应用程序的全局变量,对于全局对象自动调用构造函数;

(5)进入应用程序入口点函数开始执行。

3、怎么判断数据分配到栈上还是在堆上呢?

局部变量肯定是在栈上,而通过malloc和new申请的空间是在堆上。 

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/923068.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号