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

2023-12-06 21:08

本文主要是介绍全局静态存储区、堆区和栈区深入剖析,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

在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++中,虽然可以自由操作内存,但这种技术就像是一把双刃剑,用好了锋利无比,用不好反而会造成一些自己都不能理解的莫名其妙的结果。深入理解内存的分配方式,对于实际编程是大有助益的。

这篇关于全局静态存储区、堆区和栈区深入剖析的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/463330

相关文章

SQLyog中DELIMITER执行存储过程时出现前置缩进问题的解决方法

《SQLyog中DELIMITER执行存储过程时出现前置缩进问题的解决方法》在SQLyog中执行存储过程时出现的前置缩进问题,实际上反映了SQLyog对SQL语句解析的一个特殊行为,本文给大家介绍了详... 目录问题根源正确写法示例永久解决方案为什么命令行不受影响?最佳实践建议问题根源SQLyog的语句分

MySQL数据库约束深入详解

《MySQL数据库约束深入详解》:本文主要介绍MySQL数据库约束,在MySQL数据库中,约束是用来限制进入表中的数据类型的一种技术,通过使用约束,可以确保数据的准确性、完整性和可靠性,需要的朋友... 目录一、数据库约束的概念二、约束类型三、NOT NULL 非空约束四、DEFAULT 默认值约束五、UN

Java Stream流使用案例深入详解

《JavaStream流使用案例深入详解》:本文主要介绍JavaStream流使用案例详解,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录前言1. Lambda1.1 语法1.2 没参数只有一条语句或者多条语句1.3 一个参数只有一条语句或者多

关于MongoDB图片URL存储异常问题以及解决

《关于MongoDB图片URL存储异常问题以及解决》:本文主要介绍关于MongoDB图片URL存储异常问题以及解决方案,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录MongoDB图片URL存储异常问题项目场景问题描述原因分析解决方案预防措施js总结MongoDB图

深入理解Apache Kafka(分布式流处理平台)

《深入理解ApacheKafka(分布式流处理平台)》ApacheKafka作为现代分布式系统中的核心中间件,为构建高吞吐量、低延迟的数据管道提供了强大支持,本文将深入探讨Kafka的核心概念、架构... 目录引言一、Apache Kafka概述1.1 什么是Kafka?1.2 Kafka的核心概念二、Ka

Java并发编程必备之Synchronized关键字深入解析

《Java并发编程必备之Synchronized关键字深入解析》本文我们深入探索了Java中的Synchronized关键字,包括其互斥性和可重入性的特性,文章详细介绍了Synchronized的三种... 目录一、前言二、Synchronized关键字2.1 Synchronized的特性1. 互斥2.

C# WinForms存储过程操作数据库的实例讲解

《C#WinForms存储过程操作数据库的实例讲解》:本文主要介绍C#WinForms存储过程操作数据库的实例,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、存储过程基础二、C# 调用流程1. 数据库连接配置2. 执行存储过程(增删改)3. 查询数据三、事务处

Oracle存储过程里操作BLOB的字节数据的办法

《Oracle存储过程里操作BLOB的字节数据的办法》该篇文章介绍了如何在Oracle存储过程中操作BLOB的字节数据,作者研究了如何获取BLOB的字节长度、如何使用DBMS_LOB包进行BLOB操作... 目录一、缘由二、办法2.1 基本操作2.2 DBMS_LOB包2.3 字节级操作与RAW数据类型2.

一文带你深入了解Python中的GeneratorExit异常处理

《一文带你深入了解Python中的GeneratorExit异常处理》GeneratorExit是Python内置的异常,当生成器或协程被强制关闭时,Python解释器会向其发送这个异常,下面我们来看... 目录GeneratorExit:协程世界的死亡通知书什么是GeneratorExit实际中的问题案例

Linux系统中配置静态IP地址的详细步骤

《Linux系统中配置静态IP地址的详细步骤》本文详细介绍了在Linux系统中配置静态IP地址的五个步骤,包括打开终端、编辑网络配置文件、配置IP地址、保存并重启网络服务,这对于系统管理员和新手都极具... 目录步骤一:打开终端步骤二:编辑网络配置文件步骤三:配置静态IP地址步骤四:保存并关闭文件步骤五:重