(C++) 详解内存地址空间

news2024/11/17 0:41:29

详解内存空间

0. 概述

一个C/C++ 程序,编译之后,形成的程序,在执行期间,内存中不仅存在一块区域用于存放代码,还有一些其他的区域用于使用,本节会详解C/C++内部所使用的内存地址空间,关于各内存的作用、位置做一个整体概述。

1. C++ 内存布局

操作系统的内存布局可大致分为两块:内核态和用户态,此处的内核态和用户态,不同于操作系统在执行时所进入的内核态和用户态,此处专指内存。二者有类似之处,例如:只有操作系统处于内核态时才可以访问内核态内存,因此二者容易产生混淆。

仅需了解,此处指代:内存内核态 和 内存用户态。

内存内核态暂且不去深究,内存用户态在C++程序执行时,会划分成以下内容:

【栈、堆、全局/静态区、文字常量区、程序代码区】(地址从高到低)

2. 内存分区

在这里插入图片描述

3. 栈区

栈:用于存放局部变量、函数参数、函数调用返回值、函数调用返回地址等数据,程序从main 主函数开始运行,到主函数运行结束,在此之间调用其他函数,可看作将其他函数进行压栈的一个过程,在栈区内的变量、地址等,当该函数执行结束后,其中的资源由系统自动释放。如main 函数中调用 func 函数,func 函数内生成一个数据,将其作为返回值进行返回。main 函数中使用变量进行接收,打印,可以看出打印值不同于 func 函数中的值(未定义行为),当func 返回后,该函数出栈,其中的资源被系统释放。

示例如下:

char *func() {
    char buf[] = "hello world";
    return buf;
}
int main(int argc, char *argv[]) {
    char *buf = func();
    cout << "buf = " << buf << endl;
    return 0;
}

另外值得注意的一点是,栈区的使用,操作方式类似于数据结构中的栈,即在使用时,后进先出,函数调用机制使用栈区完成,大量频繁的调用栈区,务必会造成时间资源的消耗,导致程序的执行效率下降。C 语言解决方法是使用宏代替短小频繁的函数体,C++ 语言的解决方法是使用内联函数进行替换,还需提高编程技巧。

机器在栈上申请的空间有限,因此在栈上使用的内存需要注意大小。

4. 堆区

堆位于栈区下,全局/静态区上,栈区向下生长,堆区向上生长,因此日常提到堆栈,是因为这两者的内存空间十分接近。

堆区是程序员可手动分配的内存空间,特点是需要手动申请和手动释放,在C语言中使用 malloc 和 free 进行申请和释放。C++中则使用 new 和 delete 进行申请和释放,此处不再赘述 malloc/free 和 new/delete 的区别,若感兴趣请自行查询相关资料。

堆区申请的数据在程序执行阶段不会被系统所自动释放,因此C和C++程序员需要注意内存大小,内存释放问题。(程序结束时会被操作系统回收)

需要注意:

1.申请堆内存之后,立刻验证内存空间是否申请成功。

2.申请行为必须对应释放行为,有申请内存,则必有释放行为,因此写 malloc 之后立刻写上free语句。new/delete 同理。

3.free 和 delete 虽然传入的是指针,但释放的确是内存空间,因此需要将该指针置为null,防止野指针问题。

另外,堆的运行速度、效率不及栈,且存在内存碎片问题。 使用 malloc 和 free 时,需要添加头文件。

5. 全局/静态区

全局区、静态区是一片区域,原因在于全局变量和静态变量的内存地址都位于这片空间下。该空间位于堆下,低地址。

定义一个变量时,需要及时进行初始化,变量被定义 static 之后,只有当前模块可见。当一个局部变量被定义为 static时,虽然该局部变量的可见范围仍然属于该函数,但该局部变量的生命周期已经延长到了程序生存期。

6. 文字常量区(只读)

文字常量区用于定义常量字符串,程序结束后由系统进行释放,不可进行写操作。

const char* 定义文字常量后,直接使用字符串,二者处于的地址相同,都位于文字常量区。

#include <func.h>

#include <iostream>
using std::cout;
using std::endl;

int main(int argc, char *argv[]) {
    const char *str = "Hello world";
    printf("str address = %p\n", str);
    printf("hw  address = %p\n",&"Hello world");
    return 0;
    // str address = 0x561f4d567004
	// hw  address = 0x561f4d567004
}

局部的常量字符串放在栈或者文字常量区,视编译器而定。

7. 程序代码区(只读)

顾名思义,存放程序代码的位置,函数也是存放在某个内存地址的,比如,可以打印看一下main函数的运行地址。

#include <iostream>
using std::cout;
using std::endl;

int main(int argc, char *argv[]) {
    printf("main address =  %p\n", &main);
    return 0;
}

参考:https://www.cnblogs.com/songdanzju/p/7422507.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1462875.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Java下访问SQLServer 2008(低于2016)数据连接问题

环境&#xff1a;ubuntu20.04&#xff0c;tomcat&#xff0c;java 通过jdbc:sqlserver连接远程的SQLServer 2008R2数据库&#xff0c;2016版本之前仅支持TLS10&#xff0c;因此在连接时会出现如下错误&#xff0c; The driver could not establish a secure connection to SQ…

(二十二)Flask之上下文管理第三篇【收尾—讲一讲g】

目录&#xff1a; 每篇前言&#xff1a;g到底是什么&#xff1f;生命周期在请求周期内保持数据需要注意的是&#xff1a; 拓展—面向对象的私有字段深入讲解一下那句&#xff1a; 每篇前言&#xff1a; &#x1f3c6;&#x1f3c6;作者介绍&#xff1a;【孤寒者】—CSDN全栈领域…

Java项目:21 基于SSM实现的图书借阅管理系统

作者主页&#xff1a;舒克日记 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 基于SSM实现的图书借阅管理系统设计了两个角色&#xff0c;分别是管理员、用户&#xff0c;在数据表user中以ident字段区分&#xff0c;为1表示管理员…

Vue中如何使用dayjs

Day.js中文网Day.js是一个极简的JavaScript库&#xff0c;可以为现代浏览器解析、验证、操作和显示日期和时间。https://dayjs.fenxianglu.cn/ 单位不区别大小写&#xff0c;支持复数和缩写形式 单位缩写描述 date D日期 [1,31]dayd星期 [0,6]&#xff08;星期日0&#xff0c…

【开源】JAVA+Vue.js实现超市账单管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块三、系统设计3.1 总体设计3.2 前端设计3.3 后端设计在这里插入图片描述 四、系统展示五、核心代码5.1 查询供应商5.2 查询商品5.3 新增超市账单5.4 编辑超市账单5.5 查询超市账单 六、免责说明 一、摘要 1.1 项目介绍 基于…

尾矿库排洪系统结构仿真软件WKStruc(可试用)

1、背景介绍 尾矿库作为重大危险源之一&#xff0c;在国际灾害事故排名中位列第18位&#xff0c;根据中国钼业2019年8月刊《中国尾矿库溃坝与泄漏事故统计及成因分析》的统计&#xff0c;在46起尾矿库泄漏事故中&#xff0c;由于排洪设施导致的尾矿泄漏事故占比高达1/3&#x…

【SpringCloud】使用 Spring Cloud Alibaba 之 Sentinel 实现微服务的限流、降级、熔断

目录 一、Sentinel 介绍1.1 什么是 Sentinel1.2 Sentinel 特性1.3 限流、降级与熔断的区别 二、实战演示2.1 下载启动 Sentinel 控制台2.2 后端微服务接入 Sentinel 控制台2.2.1 引入 Sentinel 依赖2.2.2 添加 Sentinel 连接配置 2.3 使用 Sentinel 进行流控&#xff08;含限流…

【LeetCode: 105. 从前序与中序遍历序列构造二叉树 + DFS】

&#x1f680; 算法题 &#x1f680; &#x1f332; 算法刷题专栏 | 面试必备算法 | 面试高频算法 &#x1f340; &#x1f332; 越难的东西,越要努力坚持&#xff0c;因为它具有很高的价值&#xff0c;算法就是这样✨ &#x1f332; 作者简介&#xff1a;硕风和炜&#xff0c;…

【精选】Java面向对象进阶——内部类

&#x1f36c; 博主介绍&#x1f468;‍&#x1f393; 博主介绍&#xff1a;大家好&#xff0c;我是 hacker-routing &#xff0c;很高兴认识大家~ ✨主攻领域&#xff1a;【渗透领域】【应急响应】 【Java】 【VulnHub靶场复现】【面试分析】 &#x1f389;点赞➕评论➕收藏 …

设计师常常从哪些网站获取灵感?

1、Pinterest Pinterest是一个基于图片共享的社交网站。用户可以在平台上浏览、收集和分享各种想法、设计灵感和项目。Pinterest用户可以在其网站或应用程序上创建虚拟画板&#xff08;boards&#xff09;&#xff0c;根据主题或兴趣收集和整理你最喜欢的图片&#xff08;包括…

RxJS 核心原理-操作符(源码实现)

本文将深入探讨RXJS操作符的核心原理&#xff0c;并介绍一些常见的操作符、应用场景以及相应的代码示例。通过理解RXJS的响应式编程思想&#xff0c;您将能够更好地应用它来处理异步数据流和事件流。 建议读者在阅读本文之前&#xff0c;先参考我的另一篇文章《深入浅出 RxJS …

IDM(Internet Download Manager)2024免激活绿色版下载

IDM&#xff08;Internet Download Manager&#xff09;在安全保护方面提供了多种功能和策略&#xff0c;以确保用户的下载体验和数据安全。以下是一些IDM的安全保护功能和策略&#xff1a; IDM绿色下载如下: https://wm.makeding.com/iclk/?zoneid34275 病毒扫描功能&#…

Spring之AOP源码解析(中)

前言 在上一篇文章中,我们讲解了Spring中那些注解可能会产生AOP动态代理,我们通过源码发现,完成AOP相关操作都和ProxyFactory这个类有密切关系,这一篇我们将围绕这个类继续解析 演示 作用 ProxyFactory采用策略模式生成动态代理对象,具体生成cglib动态代理还是jdk动态代理,…

FairyGUI × Cocos Creator 3.x 使用方式

前言 上一篇文章 FariyGUI Cocos Creator 入门 简单介绍了FairyGUI&#xff0c;并且按照官方demo成功在Cocos Creator2.4.0上运行起来了。 当我今天使用Creator 3.x 再引入2.x的Lib时&#xff0c;发现出现了报错。 这篇文章将介绍如何在Creator 3.x上使用fgui。 引入 首先&…

想把握现货黄金价格走势 这两点能助你掌握优势

现货黄金价格走势很是狡猾&#xff0c;想要抓准它的波动是很难的。但我们作为投资者&#xff0c;偏要与它较劲。想要像捕捉猎物一样捕捉到现黄金价格走势&#xff0c;以下这两点投资者要注意。 了解清楚自己的风格适合什么市场&#xff1f;投资者有比较固定的投资风格&#xff…

Day4. 文件IO的基本概念和读写

温习&#xff1a; 文件的拷贝&#xff08;单个字符&#xff09;(fgetc/fputc) #include <stdio.h>int main(void) {FILE* fp NULL;FILE* fq NULL;char ch 0;fp fopen("str.txt","r");if (fp NULL){perror("file to fopen!");retur…

指南 | 从概念到实践:探索独立站在当代电商中的关键作用

搭建电商独立站指南 随着数字化时代的到来&#xff0c;电子商务已成为全球商业生态的核心组成部分。在这个不断变化的市场中&#xff0c;独立站作为企业建立在线身份和拓展业务的强大工具&#xff0c;正逐步展现出其不可替代的价值。 从概念到实践&#xff0c;本文将深入探索独…

1500W SMB TVS

TVS的简介 瞬态电压抑制二极管&#xff0c;简称TVS。当TVS两极受到反向瞬态高能量冲击时&#xff0c;它能以 10- s的速度&#xff0c;将其两极间的高阻抗变为低阻抗&#xff0c;吸收高达数千瓦的浪涌功率&#xff0c;使两极间的电压钳位于一个预定值&#xff0c;有效地保护电子…

Linux环境安装Git(详细图文)

说明 此文档Linux环境为&#xff1a;Ubuntu 22.04&#xff0c;本文档介绍两种安装方式&#xff0c;一种是服务器能联网的情况通过yum或apt命令下载&#xff0c;第二种采用源码方式安装。 一、yum/apt方式安装 1.yum方式安装Git 如果你的服务器环境是centos/redhot&#xff…

理论学习-ARM-内核

ARM内核 函数的调用加载、存储计算中断异常线程的切换注意事项参考文献 为了提高学习效率&#xff0c;我们要提前想好学习策略。 首先&#xff0c;使用频率越高的知识点&#xff0c;越要首先学习。假使&#xff0c;我们学习了一个知识点&#xff0c;能覆盖工作中80%的工作量&am…