堆和栈的内存分布&一些关于内存泄露、栈溢出和野指针的内容(头秃
内存泄漏&栈溢出
C++中,我们主要涉及的内存是栈和堆,
堆 (By programmer) 申请后由程序员主动释放,遗忘后果严重;
栈 (By compiler)需要时由编译器分配,在不需要时自动清除的存储区。一般用于存放局部变量、函数参数。
这些存放在栈中的数据只在当前函数及下一层函数中有效,一旦函数返回了,会发生自动释放。
除此外还有
静态存储区 全局&静态变量在同一块内存中;
常量存储区 常量、不允许修改;
代码区 不允许修改、可执行;
回到发生内存泄漏的场景。
通常来说,一个线程的栈内存是有限的。栈上的内存通常是由编译器来自动管理的。当在栈上分配一个新的变量时,或进入一个函数时,栈的指针会下移,相当于在栈上分配了一块内存,当这个变量的生命周期结束时,栈的指针会上移。
由于栈上的内存的分配和回收都是由编译器控制的,所以在栈上是不会发生内存泄露的,只会发生栈溢出(Stack Overflow),也就是分配的空间超过了规定的栈大小。而当在堆上申请内存后忘记使用 free/delete 来回收,就发生了内存泄露。
内存泄漏检测
https://www.cnblogs.com/skynet/archive/2011/02/20/1959162.html 不赘述
野指针
指向一个已删除的对象或未申请访问受限内存区域的指针。
需要通过养成良好的编程习惯来尽力减少。对野指针进行操作很容易造成程序错误。
指针变量未初始化
创建新指针时应该对其初始化,设置为NULL或者指向合法的内存,不然会被随机指向任意空间。
野指针指针释放后之后未置空
free或delete只是把指针所指的内存给释放掉,但并没有结束指针本身。释放后的指针应立即将指针置为NULL,防止产生“野指针”。
野指针指针操作超越变量作用域
不要返回指向栈内存的指针或引用,因为栈内存在函数结束时会被释放。
class A
{
public:
void Func(void)
{
cout << “Func of class A” << endl;
}
}; class B
{
public:
A *p;
void Test(void)
{
A a;
p = &a; //a是函数Test中的局部量,而不属于整个class B
}
void Test1()
{
p->Func(); // p 是“野指针”
}
};
a在void Test(void)函数结束时会被释放,所以在函数void Test1()中的指针p就是野指针。
在堆上,还是在栈上?
如果需要在堆上创建对象,则使用new运算符或者malloc系列函数。
Object obj;
有什么含义?
使对象obj具有“自动存储(automatic storage)”的性质。所谓“自动存储”,意思是这个对象的存储位置取决于其声明所在的上下文。
如果这个语句出现在函数内部,那么它就在栈上创建对象。
如果这个语句不是在函数内部,而是作为一个类的成员变量,则取决于这个类的对象发生分配时的实际场景。
1.
class Class
{
Object obj;
}; Class *pC = new Class;
类的指针pC在堆上创建,于是pC->obj也在堆上创建。
2.
Object *pObj;
pObj = new Object;
同意,指针pObj是“自动存储”的。
而下面一行语句则指出,这个指针所指向的对象是在堆上面分配的。如果这两行语句出现在一个函数内部,意味着当函数结束时,pObj会被销毁,但是它指向的对象不会。因此,为了继续使用这个对象,通常我们会在函数最后添加一个return语句,或者使用一个传出参数。否则的话,这个在堆上创建的对象就没有指针指向它,换而言之,发生了内存泄漏。
3.指针指向一个在栈上创建的对象:
Object obj;
Object *pObj = &obj;
4.有些情况,即便你在栈上创建了对象,它还是会占用堆的空间
void func
{
std::vector v;
}
对象v在栈上,因为vector类在堆上存储数据,即v所管理的数据在堆上。
堆和栈
堆和栈的区别在于两点:
- 生命周期
- 性能
第一点才是我们需要着重考虑的。在栈上的对象不需要我们手动管理内存,所以推荐能在栈上创建变量就老实一点。然而如果一个必要的比其所在的上下文更长生命周期的对象变量需要被创建的时候,需要慎重的去考虑。
除了函数内部的变量和成员变量。还有两类变量:全局变量和static变量:它们即不在堆上创建,也不在栈上创建。它们有自己的内存空间,是除堆和栈以外的数据区。也就是说,当实例对象即不在函数内部,又不是类的成员变量时,这个对象会在全局数据段创建,同理适用于static变量。
对于指针,如果这个语句出现在函数内部或类的成员变量,正如我们前面所说的,这个指针是自动存储的。但是,如果这个语句是在类的外部,它就是在全局数据段创建的。虽然它指向的对象可能在堆上创建,也可能在栈上创建。
堆和栈的内存分布&一些关于内存泄露、栈溢出和野指针的内容(头秃的更多相关文章
- JVM内存结构之堆、栈、方法区以及直接内存、堆和栈区别
JVM内存结构之堆.栈.方法区以及直接内存.堆和栈区别 一. 理解JVM中堆与栈以及方法区 堆(heap):FIFO(队列优先,先进先出):二级缓存:*JVM中只有一个堆区被所有线程所共享:对象和数 ...
- .NET的堆和栈03,引用类型对象拷贝以及内存分配
在" .NET的堆和栈01,基本概念.值类型内存分配"中,了解了"堆"和"栈"的基本概念,以及值类型的内存分配.我们知道:当执行一个方法的时 ...
- binary hacks读数笔记(堆、栈 VMA的分布)
一.首先看一个简单的程序: #include<stdlib.h> int main() { while(1) { sleep(1000); } return 0; } gcc -stati ...
- .NET的堆和栈01,基本概念、值类型内存分配
当我们对.NET Framework的一些基本面了解之后,实际上,还是很有必要了解一些更底层的知识.比如.NET Framework是如何进行内存管理的,是如何垃圾回收的......这样,我们才能写出 ...
- (十一)C语言中内存堆和栈的区别
在计算机领域,堆栈是一个不容忽视的概念,我们编写的C语言程序基本上都要用到.但对于很多的初学着来说,堆栈是一个很模糊的概念. 堆栈:一种数据结构.一个在程序运行时用于存放的地方,这可能是很多初学者的认 ...
- NET的堆和栈04,对托管和非托管资源的垃圾回收以及内存分配
在" .NET的堆和栈01,基本概念.值类型内存分配"中,了解了"堆"和"栈"的基本概念,以及值类型的内存分配.我们知道:当执行一个方法的时 ...
- .NET的堆和栈02,值类型和引用类型参数传递以及内存分配
在" .NET的堆和栈01,基本概念.值类型内存分配"中,了解了"堆"和"栈"的基本概念,以及值类型的内存分配.我们知道:当执行一个方法的时 ...
- 栈 堆 stack heap 堆内存 栈内存 内存分配中的堆和栈 掌握堆内存的权柄就是返回的指针 栈是面向线程的而堆是面向进程的。 new/delete and malloc/ free 指针与内存模型
小结: 1.栈内存 为什么快? Due to this nature, the process of storing and retrieving data from the stack is ver ...
- Java堆和栈详解
Java把内存分成两种,一种叫做栈内存,一种叫做堆内存 在函数中定义的一些基本类型的变量和对象的引用变量都是在函数的栈内存中分配.当在一段代码块中定义一个变量时,java就在栈中为这个变量分配内存空间 ...
随机推荐
- .NET平台系列10 .NET统一平台愿景
系列目录 [已更新最新开发文章,点击查看详细] 2019年,微软分享了[统一的.NET堆栈和生态系统的愿景].给开发者带来的价值是,将能够使用一组API,语言和工具来针对广泛的应用程序类型,包 ...
- [Qt] 事件机制(一)
事件主要分为两种: 在与用户交互时发生.比如按下鼠标(mousePressEvent),敲击键盘(keyPressEvent)等 系统自动发生,比如计时器事件(timerEvent)等 每种事件对应一 ...
- [算法] O(n^2)排序算法的效率比较
选择.插入排序 main.cpp 1 #include <iostream> 3 #include "SortTestHelper.h" 4 5 using names ...
- 解决 Ubuntu 无法使用 root 用户进行 ssh 远程登陆
解决 Ubuntu 无法使用 root 用户进行 ssh 远程登陆 操作系统 Ubuntu 20.04.2 LTS 一.修改sshd配置文件 //打开 /etc/ssh/sshd_config 配置文 ...
- SVN库迁移到GitHub
创建新目录,cmd进入到新目录,执行如下命令: git svn init svn://10.10.10.10/net/QA_Dept git svn fetch git remote add orig ...
- Linux系统(控制节点)部署环境
环境部署 重点说明:安装ansible时去控制Windows机器,由于需要在Linux系统上安装pywinrm插件,而使用yum安装锝ansible是无法调用pywinrm插件,所以整体使用pip工具 ...
- stm32.cube(一)——系统架构及目录结构
一.前言 Arm的应用场景往往比51单片机复杂得多,如果一个高级应用的开发需要连底层的结构性代码都要重构,那么在成本和研发周期上就会面临巨大的风险.为了简化编码过程,芯片厂商经常会提供一些板卡级支持的 ...
- mysql中的实例、数据库关系简介
MySQL是单进程多线程(而Oracle等是多进程),也就是说MySQL实例在系 统上表现就是一个服务进程,即进程(通过多种方法可以创建多实例,再安装一个端口号不同的mysql,或者通过workben ...
- Java安全之Cas反序列化漏洞分析
Java安全之Cas反序列化漏洞分析 0x00 前言 某次项目中遇到Cas,以前没接触过,借此机会学习一波. 0x01 Cas 简介 CAS 是 Yale 大学发起的一个开源项目,旨在为 Web 应用 ...
- 『动善时』JMeter基础 — 35、JMeter接口关联【JSON提取器】详解
目录 1.JSON提取器介绍 2.JSON提取器界面详解 3.JSON提取器的使用 (1)测试计划内包含的元件 (2)HTTP Cookie管理器内容 (3)用户登陆请求界面内容 (4)JSON提取器 ...