多线程中堆和栈区别的深入解析
很多现代操作系统中,一个进程的(虚)地址空间大小为4G,分为系统空间和用户空间两部分,系统空间为所有进程共享,而用户空间是独立的,一般WINDOWS进程的用户空间为2G。
一个进程中的所有线程共享该进程的地址空间,但它们有各自独立的(私有的)栈(stack),Windows线程的缺省堆栈大小为1M。堆(heap)的分配与栈有所不同,一般是一个进程有一个C运行时堆,这个堆为本进程中所有线程共享,Windows进程还有所谓进程默认堆,用户也可以创建自己的堆。
堆: 是大家共有的空间,分全局堆和局部堆。全局堆就是所有没有分配的空间,局部堆就是用户分配的空间。堆在操作系统对进程初始化的时候分配,运行过程中也可以向系统要额外的堆,但是记得用完了要还给操作系统,要不然就是内存泄漏。
栈:是个线程独有的,保存其运行状态和局部自动变量的。栈在线程开始的时候初始化,每个线程的栈互相独立,因此,栈是 thread safe的。操作系统在切换线程的时候会自动的切换栈,就是切换 SS/ESP寄存器。栈空间不需要在高级语言里面显式的分配和释放。
参考资料: 进程线程与栈 堆的关系(转)
一篇文章:
最初涉及多线程程序涉及的时候经常会出现一些令人难以思议的事情,用堆和栈分配一个变量可能在以后的执行中产生意想不到的结果,而这个结果的表现就是内存的非法被访问,导致内存的内容被更改。
理解这个现象的两个基本概念是:在一个进程的线程共享堆区,而进程中的线程各自维持自己堆栈。
另一运行机制就是如果声明一个成员变量 如 char Name[200],随着这段代码调用的结束,Name在栈区的地址被释放,而如果是 char * Name = new char[200]; 情况则完全不同,除非显示调用delete否则 Name指向的地址不会被释放。
理解了线程对 堆栈 的可见性,和内存管理机制就能推测出笔者伊始提出的现象。
用一个 实例来深入理解这种机制。
在线程 1 中,
A ()
{
B();
C();
}
B()
{
栈 or 堆分配变量 V;
将V的地址插入 公共队列;
}
线程 2 中:
D()
{
while(1)
{
处理公共队列;
}
}
在B中如果用栈区 即采用临时变量的机制分配声明V和堆区,而者的结果是不同的。如果用栈区,如果变量地址为Am1-Am2这么大,退出B调用时候这段地址被释放,C函数可能将这段内存改写;这样当D执行的时候,从内存Am1-Am2中读取的内容就是被改过的了。
而如果用New(堆)分配,则不会出现那样的情况,因为没有显示对用delete并且堆对于线程共享,即2线程可以看到1线程在堆里分配的东西,所以不会发生误写。
多线程中堆和栈区别的深入解析相关推荐
- C++中堆和栈的完全解析
C++中堆和栈的完全解析 内存分配方面: 堆: 操作系统有一个记录空闲内存地址的链表,当系统收到程序的申请时,会遍历该链表,寻找第一个空间大于所申请空间的堆结点,然后将该结点从空闲结点链表中删 除,并 ...
- Java中堆、栈、常量池等概念解析
Java中堆.栈.常量池等概念解析 程序运行时,我们最好对数据保存到什么地方做到心中有数.特别要注意的是内存的分配.有六个地方都可以保存数据: (1) 寄存器.这是最快的保存区域,因为它位于和其他所有 ...
- 当初我要是这么学习Java多线程就好了「附图文解析」
文章目录 1. 概念篇 1.1 认识进程 1.2 进程性质 1.3 操作系统如何管理进程 1.4 多线程和多进程 1.5 时间片 1.6 并发与并行 1.7 内核态与用户态 1.8 进程中的上下文 1 ...
- c++中堆、栈内存分配概念示例讲解
首先来看看主要有几种程序内存分配: 一个由C/C++编译程序占用内存分为以下几个部分 1.栈区(stack)- 由编译器自动分配释放 ,存放函数参数值,局部变量值等.其操作方式类似于数据结构中栈. 2 ...
- VMware 虚拟化编程(8) — 多线程中的 VixDiskLib
目录 目录 前文列表 多线程注意事项 多线程中的 VixDiskLib 前文列表 VMware 虚拟化编程(1) - VMDK/VDDK/VixDiskLib/VADP 概念简析 VMware 虚拟化 ...
- android串口补位,Rust多线程中的消息传递机制
代码说话. use std::thread; use std::sync::mpsc; use std::time::Duration; fn main() { let (tx, rx) = mpsc ...
- 多线程中的应用之队列(queue)
队列queue 多应用在多线程中,对于多线程访问共享变量时,队列queue是线程安全的. 从queue队列的实现来看,队列使用了1个线程互斥锁(pthread.Lock()),以及3个条件标量(pth ...
- c++中堆、栈内存分配
转自:https://blog.csdn.net/qingtingchen1987/article/details/7698415 一个由C/C++编译程序占用内存分为以下几个部分 1.栈区(stac ...
- 内存中“堆”和“栈”的区别
内存中"堆"和"栈"的区别: 程序中用来存放数据的内存分为四块,分别是: 1.全局区(静态区)(static):全局变量和静态变量都存储在这块区域,与其他变量的 ...
最新文章
- java集合sort底层实现_Java面试总结系列之Collections.sort()
- python整数和浮点数相乘_python中整数除法和浮点数到整数转换之间的区别是什么原因?...
- 「SVN」ubuntu svn自动忽略了.a.so等文件
- SQL Server时间粒度系列----第6节基于当前日的小时数和分钟数与mysql unix_timestamp和from_unixtime的mssql实现...
- 工业以太网交换机在工厂环境中使用需要注意哪些问题?
- HDU 5102 The K-th Distance
- arcsinx的图_反三角函数图像大全
- 《认知天性》:讲述基于科学的学习方法
- java后端社招面试经历
- CTF--Do you like xml
- 最优化方法 19:近似梯度下降
- 中文文案排版 - 中文排版教程
- 旋翼无人机及摄影测量基础
- 6-3 在一个数组中实现两个堆栈 (22分)
- go-pitaya学习笔记(9)-rate_limiting demo分析
- c# .net接口协定Contract
- 爬虫简单爬取网页图片
- 红外发射二极管能做接收管
- ARC133 B - Dividing Subsequence
- 地大网上报账之日常报销流程
热门文章
- 计算机科学课程体系核心内容,计算机科学教育的课程体系之研究
- python交互式shell_交互式 shell 玩转 Python
- python dlib caffe人脸相似度_基于深度学习的人脸识别系统(Caffe+OpenCV+Dlib)【一】如何配置caffe属性表...
- oracle设置开机启动,linux下oracle设置开机自启动实现方法
- java convert函数_自己实现 java中 Convert.toDouble(String str)处理函数 | 学步园
- 嵌入式开发中常用的几种通信接口总结
- 电子设计竞赛(4)-常用的两种PID算法
- 计算机文化基础课程总结,计算机文化基础课程总结.docx
- 平台和计算机技术,两大平台技术提升及优势功能PK对比
- 适合python开发的linux版本,Python Linux下安装多个版本