热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

全局静态存储区、堆区和栈区深入剖析

在C++中,内存可分为系统数据区,自由存储区,文本区,const数据区,全局静态区,堆区和栈区
在C++中,内存可分为系统数据区,自由存储区,文本区,const数据区,全局静态区,堆区和栈区。其中,系统数据区存放的是系统数据,我们是不能自由访问的,有时候windows系统会突然弹出一个消息框,内容是“内存不能为read”就是错误访问系统数据区的结果;自由存储区用来存放由C延伸而来的malloc()函数所分配的数据;文本区存放着我们的函数代码,我们调用函数时的底层行为就类似于先去操作一个指针,而这个指针就指向函数指令所在的地址,也就是在文本区中;const数据区,顾名思义,就是存放不可修改的数据的内存区域,我们定义的const变量都存放在这里。最后,我们来看全局静态存储区、堆区和栈区。

先来看全局静态存储区,在程序中,由static标号定义的数据都存放在全局静态存储区中,不论是在main()函数之外的定义的全局变量,还是在子函数中定义的局部变量,只要在定义之前有static标号,定义之后就会始终存在于全局静态存储区中。当然,在main()函数之外定义的全局静态变量在任何地方都可以访问,而在子函数中定义的局部静态变量只有在定义该变量的模块中可见。但是也存在这样一种现象:如前边所述,即使在子函数中定义的局部静态变量,其存在形式也是静态的,也就是说,只要在变量定义的语句执行之后,即使在变量不可见的地方,只要对该变量所在的地址取地址解析操作,也是可以获得该变量的值的。比如我们在函数fun()中定义了一个static int a=100;假设该变量的地址是0x0042AD54,我们在main()函数中调用fun()之后,如果对0x0042AD54取地址解析,也是可以得到100的:int* p=(int*)0x0042ad54; int b=*p;这里b被赋值100。由此,我们可以看到,凡是有static定义的变量的生命周期就是整个程序的生命周期,直到程序退出,静态变量所占据的内存才会被释放。

堆存储区的行为类似于静态存储区,当我们在堆上分配内存之后,如果不进行手动的释放,其内存是不会自动释放掉的。但是在JAVA中,有一种叫做垃圾清理的机制可以自动清理堆内存,但是在C++中没有这样的机制。也就是说,在C++中,如果我们分配了堆内存,就必须手动释放它。否则如果我们不停的分配堆内存,但是不对其进行释放,当对内存被耗尽是就会造成程序崩溃。

一般地,用new分配的变量是存放于堆内存中的,但是返回的指针变量是存放在栈中的。当我们在一个子函数中new了一个变量,但是在函数返回时既没有保存new返回的指针,也没有delete时,就会造成内存泄露。如果我们写的是服务器程序,不断地内存泄露所造成的最终结果就是服务器死机。但是在windows、linux以及其他一些成熟的系统中,都有类似于内存保护的机制。系统会给用户程序分配一定的运行所需的内存,同是也会给系统自身的运行保留一部分内存,这部分内存是用户程序所不能访问的。如果我们编写的程序存在内存泄露,当耗尽系统给应用程序分配的内存之后,程序就会停止运行,而不会造成系统的司机。

至于栈内存,也是我们在写程序中用到的最多的情况。程序中定义的每一个临时对象,new所返回的指针,以及递归函数中变量都是存放在栈中的。栈内存是可以自动释放的,当我们在某个模块中定义了一个对象,在该模块结束时,变量所占据的内存就会被系统回收,在定义新的变量时,新的变量就有可能存放在原变量所在的地址上,但是在系统回收栈内存的时候,是不会清空所释放的栈内存中的数据的,只是将栈顶重新调整,并在新数据的到来时将其分配到栈顶。

在C++中,虽然可以自由操作内存,但这种技术就像是一把双刃剑,用好了锋利无比,用不好反而会造成一些自己都不能理解的莫名其妙的结果。深入理解内存的分配方式,对于实际编程是大有助益的。
推荐阅读
  • 对于初次购买阿里云服务器的新手用户来说,如何高效地利用服务器资源并成功部署网站是一个重要的课题。本文将详细指导您完成从购买服务器到网站上线的六个关键步骤。 ... [详细]
  • 本文探讨了 Boost 库中的 Program Options 组件,这是一个强大的工具,用于解析命令行参数和配置文件。文章介绍了如何正确设置和使用该组件,包括处理复杂选项和负数值的方法。 ... [详细]
  • 本文详细介绍了在 Windows 7 上安装和配置 PHP 5.4 的 Memcached 分布式缓存系统的方法,旨在减少数据库的频繁访问,提高应用程序的响应速度。 ... [详细]
  • 深入解析轻量级数据库 SQL Server Express LocalDB
    本文详细介绍了 SQL Server Express LocalDB,这是一种轻量级的本地 T-SQL 数据库解决方案,特别适合开发环境使用。文章还探讨了 LocalDB 与其他轻量级数据库的对比,并提供了安装和连接 LocalDB 的步骤。 ... [详细]
  • 本文介绍了如何使用C# Winform开发局域网内的文件传输功能,详细描述了从用户界面到后端网络通信的具体实现。 ... [详细]
  • 本文详细介绍了如何使用 Python 编程语言中的 Scapy 库执行 DNS 欺骗攻击,包括必要的软件安装、攻击流程及代码示例。 ... [详细]
  • 本文介绍了Linux内核中TCP的三种接收队列:Prequeue、sk_receive_queue和Backlog。这些队列在数据包处理过程中扮演着重要角色,帮助提高系统性能和效率。 ... [详细]
  • 工作中频繁在不同Linux服务器之间切换时,频繁输入密码不仅耗时还影响效率。本文介绍如何通过设置SSH密钥认证,简化登录流程,提高工作效率。 ... [详细]
  • 解决远程桌面连接时的身份验证错误问题
    本文介绍了如何解决在尝试远程访问服务器时遇到的身份验证错误,特别是当系统提示‘要求的函数不受支持’时的具体解决步骤。通过调整Windows注册表设置,您可以轻松解决这一常见问题。 ... [详细]
  • 在日常运维中,频繁地对多台Linux服务器进行用户管理是一项耗时的任务。为了提高效率,可以通过编写Expect脚本来实现远程自动化操作,从而简化这一过程。 ... [详细]
  • Redis: 高效的键值存储系统
    Redis是一款遵循BSD许可的开源高性能键值存储系统,它不仅支持多种数据类型的存储,还提供了数据持久化和复制等功能,显著区别于其他键值缓存解决方案。 ... [详细]
  • 本文介绍了一个基本的同步Socket程序,演示了如何实现客户端与服务器之间的简单消息传递。此外,文章还概述了Socket的基本工作流程,并计划在未来探讨同步与异步Socket的区别。 ... [详细]
  • 最新进展:作为最接近官方声明的信息源,本文吸引了大量关注。若需获取最新动态,请访问:lkhill.com/ccie-version-5-update ... [详细]
  • 利用Cookie实现用户登录状态的持久化
    本文探讨了如何使用Cookie技术在Web应用中实现用户登录状态的持久化,包括Cookie的基本概念、优势及主要操作方法,并通过一个简单的Java Web项目示例展示了具体实现过程。 ... [详细]
  • 本文探讨了在SharePoint环境中使用BDC(Business Data Catalog)时遇到的问题及其解决策略,包括XML文件导入SSP后的不可见性问题以及与远程SQL Server 2005连接的难题。 ... [详细]
author-avatar
粗陶工作室
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有