谈一谈c/c++程序的内存布局

2023-11-11

内存布局

一个C 程序的典型内存布局由以下几部分组成,

  • 文本段
  • 初始化数据段
  • 未初始化的数据段(bss)
  • 堆区
  • 栈区
    在这里插入图片描述

文本段

文本段也叫代码段,包含编译程序的机器码。通常文本段是可共享的,因此对于频繁执行的程序(例如文本编辑器、C 编译器、shell 等),只需要在内存中保留一个副本。可执行目标文件的文本段通常是只读段,以防止程序被意外修改。

初始化数据段

初始化数据段存储所有预先初始化的全局变量、静态变量、常量和外部变量(用 extern 关键字声明的变量),注意这部分存储的变量都是由程序员显式初始化过的,而不是由编译器初始化的。该段可以进一步分为只读初始化数据段和读写初始化数据段,

#include <stdio.h>
/*  global variable stored in Initialized Data Segment in read-write area*/
char c[]="rishabh tripathi";   
/* global variable stored in Initialized Data Segment in read-only area*/  
const char s[]="HackerEarth";    
int main()
{
    static int i=11;          /* static variable stored in Initialized Data Segment*/
    return 0;
}

未初始化数据段 (bss)

在程序开始执行之前,该段中的数据被初始化为算术 0。未初始化的数据从数据段的末尾开始,包含所有初始化为 0 或在源代码中没有显式初始化的全局变量和静态变量。

bss - block started by symbol

#include <stdio.h>

char c;               /* Uninitialized variable stored in bss*/

int main()
{
    static int i;     /* Uninitialized static variable stored in bss */
    return 0;
}

堆区

堆是通常发生动态内存分配的段。当需要使用 malloccalloc 函数分配更多内存时,堆会向上增长。 堆区由进程中的所有共享库和动态加载的模块共享。

malloccalloc都是c语言中的动态内存分配的函数,此外c语言中还可以使用realloc函数重新分配内存(重新分配的内存与原内存相比,可大可小)。在c++中动态分配内存不是使用函数进行的,而是使用关键字new.

#include <stdio.h>
int main()
{
 /* memory allocating in heap segment */
    char *p=(char*)malloc(sizeof(char));   
    return 0;
}

栈区

栈区用于存储所有局部变量,用于向函数传递参数以及函数调用结束后要执行的指令的返回地址(这样函数return之后,能够接着之前的指令继续进行)。局部变量具有定义它们的块的作用域,它们是在控制进入块时创建的。所有递归函数调用都添加到堆栈中。

正是因为栈区的以上特点,我们可以看出在以下情况下,会发生栈溢出

  • 局部变量太大 (这个大可能是真的有比较大的结构体变量,类对象,局部数组,或者太多的局部变量等等)
  • 函数调用深度太深,这样我们的要返回执行的指令地址就要不停的压栈
  • 同理,如果递归深度太深,也会造成压栈太多,从而栈溢出

要解决栈溢出的问题,我们的对应的方法是,将大的对象放在堆上;避免过深的调用;递归少用(如果必须要用,那一定要做深度限制)

栈和堆通常位于进程虚拟地址的两端,然后使用时不断的向中间靠拢,当两者相遇时,也就空间耗尽了。

以上80%的内容出自下边的文章,在翻译时做了部分修改,并且加入了自己的一些理解,若有兴趣可读原文。
https://www.hackerearth.com/practice/notes/memory-layout-of-c-program/

如何查看一个程序的内存布局

在windows下可以使用size命令查看程序的内存布局,

size .\VRS.exe

我们将得到以下返回值,

   text    data     bss     dec     hex filename
 615002    8704       0  623706   9845a .\VRS.exe

上便可以看到通过size我们可以查看text data bss这三个段的大小,那么后边的dechex是什么意思呢?
dec=text+data+bss 也就是说dec是三个段的总大小,而hex是其十六进制表示。

为什么不给出堆区和栈区的大小呢?很简单,我们无法得到,因为这两个区的大小是变化的,栈在不停的压栈和出栈,堆也在动态的申请和释放,我们无法静态分析得到。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

谈一谈c/c++程序的内存布局 的相关文章

  • 如何使 Windows 窗体的关闭按钮不关闭窗体但使其不可见?

    该表单有一个 NotifyIcon 对象 当用户单击 关闭 按钮时 我希望表单不关闭而是变得不可见 然后 如果用户想再次查看该表单 可以双击系统托盘中的图标 如果用户想关闭表单 可以右键单击该图标并选择 关闭 有人可以告诉我如何使关闭按钮不
  • 无法使用已与其底层 RCW 分离的 COM 对象。在 oledb 中

    我收到此错误 但我不知道我做错了什么 下面的代码在backrgroundworker中 将异常详细信息复制到剪贴板 System Runtime InteropServices InvalidComObjectException 未处理 通
  • 访问私人成员[关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 通过将类的私有成员转换为 void 指针 然后转换为结构来访问类的私有成员是否合适 我认为我无权修改包含我需要访问的数据成员的类 如果不道德 我
  • C# 和 Javascript SHA256 哈希的代码示例

    我有一个在服务器端运行的 C 算法 它对 Base64 编码的字符串进行哈希处理 byte salt Convert FromBase64String serverSalt Step 1 SHA256Managed sha256 new S
  • 获取按下的按钮的返回值

    我有一个在特定事件中弹出的表单 它从数组中提取按钮并将标签值设置为特定值 因此 如果您要按下或单击此按钮 该函数应返回标签值 我怎样才能做到这一点 我如何知道点击了哪个按钮 此时代码返回 DialogResult 但我想从函数返回 Tag
  • linux perf:如何解释和查找热点

    我尝试了linux perf https perf wiki kernel org index php Main Page今天很实用 但在解释其结果时遇到了困难 我习惯了 valgrind 的 callgrind 这当然是与基于采样的 pe
  • 如何忽略“有符号和无符号整数表达式之间的比较”?

    谁能告诉我必须使用哪个标志才能使 gcc 忽略 有符号和无符号整数表达式之间的比较 警告消息 gcc Wno sign compare 但你确实应该修复它警告你的比较
  • 使闭包捕获的变量变得易失性

    闭包捕获的变量如何与不同线程交互 在下面的示例代码中 我想将totalEvents 声明为易失性的 但C 不允许这样做 是的 我知道这是错误的代码 这只是一个例子 private void WaitFor10Events volatile
  • 当 contains() 工作正常时,xpath 函数ends-with() 工作时出现问题

    我正在尝试获取具有以特定 id 结尾的属性的标签 like span 我想获取 id 以 国家 地区 结尾的跨度我尝试以下xpath span ends with id Country 但我得到以下异常 需要命名空间管理器或 XsltCon
  • WPF 中的调度程序和异步等待

    我正在尝试学习 WPF C 中的异步编程 但我陷入了异步编程和使用调度程序的困境 它们是不同的还是在相同的场景中使用 我愿意简短地回答这个问题 以免含糊不清 因为我知道我混淆了 WPF 中的概念和函数 但还不足以在功能上正确使用它 我在这里
  • 如何将图像和 POST 数据上传到 Azure 移动服务 ApiController 终结点?

    我正在尝试上传图片and POST表单数据 尽管理想情况下我希望它是json 到我的端点Azure 移动服务应用 我有ApiController method HttpPost Route api upload databaseId sea
  • 在数据库中搜索时忽略空文本框

    此代码能够搜索数据并将其加载到DataGridView基于搜索表单文本框中提供的值 如果我将任何文本框留空 则不会有搜索结果 因为 SQL 查询是用 AND 组合的 如何在搜索 从 SQL 查询或 C 代码 时忽略空文本框 private
  • for循环中计数器变量的范围是多少?

    我在 Visual Studio 2008 中收到以下错误 Error 1 A local variable named i cannot be declared in this scope because it would give a
  • Discord.net 无法在 Linux 上运行

    我正在尝试让在 Linux VPS 上运行的 Discord net 中编码的不和谐机器人 我通过单声道运行 但我不断收到此错误 Unhandled Exception System Exception Connection lost at
  • C++ 复制初始化和直接初始化,奇怪的情况

    在继续阅读本文之前 请阅读在 C 中 复制初始化和直接初始化之间有区别吗 https stackoverflow com questions 1051379 is there a difference in c between copy i
  • 控制到达非 void 函数末尾 -wreturn-type

    这是查找四个数字中的最大值的代码 include
  • Validation.ErrorTemplate 的 Wpf 动态资源查找

    在我的 App xaml 中 我定义了一个资源Validation ErrorTemplate 这取决于动态BorderBrush资源 我打算定义独特的BorderBrush在我拥有的每个窗口以及窗口内的不同块内
  • 如何使用 std::string 将所有出现的一个字符替换为两个字符?

    有没有一种简单的方法来替换所有出现的 in a std string with 转义 a 中的所有斜杠std string 完成此操作的最简单方法可能是boost字符串算法库 http www boost org doc libs 1 46
  • 限制C#中的并行线程数

    我正在编写一个 C 程序来生成并通过 FTP 上传 50 万个文件 我想并行处理4个文件 因为机器有4个核心 文件生成需要更长的时间 是否可以将以下 Powershell 示例转换为 C 或者是否有更好的框架 例如 C 中的 Actor 框
  • 防止索引超出范围错误

    我想编写对某些条件的检查 而不必使用 try catch 并且我想避免出现 Index Out of Range 错误的可能性 if array Element 0 Object Length gt 0 array Element 1 Ob

随机推荐

  • 计算机毕业设计Node.js+Vue基于Web的网络教学系统(程序+源码+LW+部署)

    该项目含有源码 文档 程序 数据库 配套开发软件 软件安装教程 欢迎交流 项目运行 环境配置 Node js Vscode Mysql5 7 HBuilderX Navicat11 Vue Express 项目技术 Express框架 No
  • k8s学习-DaemonSet(模板、创建、更新、回滚、删除等)

    目录 概念 模板 实战 创建 更新 回滚 回滚到上一版本 回滚到指定版本 删除 参考 概念 DaemonSet 守护进程集 在kubectl中缩写为ds 在所有节点或者是匹配的节点上都部署一个Pod 当有节点加入集群时 也会为他们新增一个
  • Unity Cinemachine之第三人称摄像机CinemachineFreeLook属性详解

    演示 CinemachineFreeLook是一个第三人称视角相机插件 功能非常强大 内置了很多属性可以供开发者根据需求进行调整 创建 首先是Cinemachine插件的导入 如果是2018以后的Unity版本 应该 可以直接从Unity顶
  • C++之:struct和class的区别

    一 数据封装和成员访问权限 1 结构体 struct 在struct中 默认的成员访问权限是public 这意味着 在结构体外部 我们可以直接访问其成员变量和成员函数 下面是一个简单的例子 struct Point int x y Poin
  • ggplot2入门

    ggplot2入门 二 3 5 几何对象 geom 和统计变换 stat 几何对象执行着图层的实际渲染 控制着生成的图像类型 各种类型图如下 示例代码如下 head mtcars library ggplot2 p lt ggplot mt
  • 自学Java做的第一个入门项目:ATM银行系统

    import java util ArrayList import java util Random import java util Scanner public class ATMSystem public static void ma
  • Unity中协程和线程区别

    协程和线程的效果类似 都可以实现与主线程异步的效果 但是本质不一样 协程在主线程内 通过软件手段实现函数与主线程的异步效果 Startcoroutine IEnumerator Func IEnumerator是迭代器关键字 修饰一个函数
  • 标准单元库---NLDM/CCS library model

    Timing Model 数字芯片设计 除了全定制设计外 绝大部分都是基于std cell的半定制设计 那么std cell的模型就极为重要 尤其半定制 需要把一个std cell看成block box 只考虑其input output p
  • python发送邮件的乱码问题解决方案

    公司项目中需要通过后台发送邮件 邮件内容包括图片附件 如果通过PHPmailer发送 由于邮件服务器可能存在延迟现象 通过PHPmailer发送邮件 需要等待邮件发送成功后才能返回结果 这在实践中证明 有时发送邮件无法即时返回结果 影响用户
  • Python内容聚合

    Python3 教程 Python 标准库概览 pip 设置代理 设置代理 PyCharm支持的4种Python Interpreter和配置方法 Python中import的as语法 Python安装自己的代码到site packages
  • python 停止线程

    import threading import time import inspect import ctypes def async raise tid exctype raises the exception performs clea
  • MySQL索引命中与失效

    目录 创建表 MySQL执行优化器 索引的命中与失效情况 总结 拓展 讨论MySQL索引命中与失效 我们得先来创建表 创建表 SET NAMES utf8mb4 SET FOREIGN KEY CHECKS 0 Table structur
  • 动态规划记录 [动态更新]

    2021 江西省赛A 题目链接 https ac nowcoder com acm contest 21592 A 题意 给出一个布尔矩阵 每个位置的值非零即一 然后问给定p和q 问从 1 1 n m 的所有路径中至少通过p次0 q次1的路
  • Java技术栈(跳槽,面试必备)

    Java技术栈 来到北京后 感觉氛围有点浮躁 人员流动性很大 很少有人能沉下心学习 所以最近打算把整理过的知识点拿出来给大家分享下 基础扎实了 无论是工作还是跳槽都很有用 跳槽前将知识点整理成word打印出来 然后背其中的知识点 保证你能面
  • 【渗透测试】常见的数据库

    一 网站暴库漏洞 暴库 就是通过一些技术手段或者程序漏洞得到数据库的地址 并将数据非法下载到本地 黑客非常乐意于这种工作 为什么呢 因为黑客在得到网站数据库后 就能得到网站管理账号 对网站进行破坏与管理 黑客也能通过数据库得到网站用户的隐私
  • GitHub 组织是什么?您应该使用一个吗?

    GitHub 作为一个平台 被个人程序员和大型组织所使用 无论您与多少人一起工作 GitHub Organizations 都为管理多个项目的人员提供了一些不错的工具 GitHub 组织是什么 GitHub Organizations 是
  • 解决linux mysql命令 bash: mysql: command not found 的方法

    解决linux mysql命令 bash mysql command not found 的方法 腾讯云开发者社区 腾讯云 tencent com
  • 服务器的安装与维护技巧——数据湾

    机房服务器的安装与维护是机房管理中的主要任务 安装维护好服务器才能保证服务器正常 安全稳定地运行 才能确保数据的安全 服务器生产的厂家 类型 系列不同其具体的安装维护方法 步骤是有差异的 本文主要以戴尔 DELL 系列服务器为例介绍服务器的
  • 数据结构经典算法集锦

    数据结构经典算法集锦 第2章 线性表 KMP算法 获得next数组 void GetNext char t int next MAX int i 1 j 0 next 1 0 设t 0 中为字符串长度 字符保存在t 1 之后 while i
  • 谈一谈c/c++程序的内存布局

    文章目录 内存布局 文本段 初始化数据段 未初始化数据段 bss 堆区 栈区 如何查看一个程序的内存布局 内存布局 一个C 程序的典型内存布局由以下几部分组成 文本段 初始化数据段 未初始化的数据段 bss 堆区 栈区 文本段 文本段也叫代