C语言程序在内存中是怎样布局的

news2024/11/15 8:38:15

理论

我们假设在32位Linux下进行编程,首先要明确,我们的虚拟地址空间有4G,4G的地址空间的寻址范围就是 0x0000_0000 ~ 0xFFFF_FFFF,在Linux下,高地址的1G内存是给操作系统使用的,也就是 0xC000_0000 ~ 0xFFFF_FFFF,这一段地址我们无法使用,可以使用的只有 0x0000_0000~0xBFFF_FFFF这一段地址。

其次要知道程序会分为那些段

  • .text 代码段:可执行程序代码(只读)
  • .rodata 只读数据段: 程序中的常量(只读)
  • .data 初始化数据段: 程序中已经初始化的全局变量。(可读可写)
  • .bss 未初始数据段: 程序中未初始的全局变量。(可读可写)
  • heap 堆区:程序中动态分配的内存。堆的内存向上增长。(可读可写)
  • 共享数据区:
  • stack 栈区:程序中的函数、函数的形参、函数的局部变量 。(可读可写)

我们的程序,编译为汇编文件的过程中,会有很多的节(section),链接器将这些目标文件中属性相同的节(section)合并成段(segment),因此一个段是由多个节组成的,我们平时所说的C程序内存空间中的数据段、代码段就是指合并后的segment。

为什么要将section合并成segment?这么做的原因也很简单,一是为了保护模式下的安全检查,二是为了操作系统在加载程序时省事。在保护模式下对内存的访问必须要经过段描述符,段描述符用来描述一段内存区域的访问属性,其中的S位和TYPE位可组合成多种权限属性,处理器用这些属性来限制程序对内存的使用,如果程序对某片内存的访问方式不符合该内存所对应的段描述符(由访问内存时所使用的选择子决定)中设置的权限,比如对代码这种具备只读属性的内存区域执行了写操作,处理器会检查到这种情况并抛出GP异常。

扯远了,那么我们的内存布局就可以看下面这个图:

请添加图片描述

其中多了一个区域 dynamic library 动态装载区,这个区域用于映射装载的动态链接库。在Linux下,如果可执行文件依赖其他共享库,那么系统就会为它在从0x40000000开始的地址分配相应的空间,并将共享库载入到该空间。

其中我们发现,蓝色的是只读的,橘色的是可读可写的数据,红色的是堆栈。其实其存放是按照权限来的,这也符合我们上面将的和操作系统对权限的检查相吻合。

实例

只讲理论是很难理清的,我们举个例子

我们写个c的程序

#include <stdlib.h>

int main(){
	int i = 0;
	while (1) {
		sleep(1000);
	}
	return 0;
}

编译一下

gcc temp.c -o temp.out -fno-pic -m32

其中 -no-pie 是不将程序地址随机化,-m32是将程序编译为32位程序,因为现在使用的都是64位系统,我们这里只讲32位,实际上本质是一样的。

执行这个程序

./temp.out

找到这个程序的pid

ps -C temp.out

得到程序的PID

➜  ~ ps -C temp.out
    PID TTY          TIME CMD
  33862 pts/2    00:00:00 temp.out

根据PID获取程序的内存映射

pmap -d 33862

得到内存映射关系

➜  ~ pmap -d 34204                      
34204:   ./temp.out
Address           Kbytes Mode  Offset           Device    Mapping
0000000008048000       4 r---- 0000000000000000 008:00005 temp.out
0000000008049000       4 r-x-- 0000000000001000 008:00005 temp.out
000000000804a000       4 r---- 0000000000002000 008:00005 temp.out
000000000804b000       4 r---- 0000000000002000 008:00005 temp.out
000000000804c000       4 rw--- 0000000000003000 008:00005 temp.out
00000000f7d25000     100 r---- 0000000000000000 008:00005 libc-2.31.so
00000000f7d3e000    1388 r-x-- 0000000000019000 008:00005 libc-2.31.so
00000000f7e99000     464 r---- 0000000000174000 008:00005 libc-2.31.so
00000000f7f0d000       4 ----- 00000000001e8000 008:00005 libc-2.31.so
00000000f7f0e000       8 r---- 00000000001e8000 008:00005 libc-2.31.so
00000000f7f10000       4 rw--- 00000000001ea000 008:00005 libc-2.31.so
00000000f7f11000      12 rw--- 0000000000000000 000:00000   [ anon ]
00000000f7f28000       8 rw--- 0000000000000000 000:00000   [ anon ]
00000000f7f2a000      16 r---- 0000000000000000 000:00000   [ anon ]
00000000f7f2e000       8 r-x-- 0000000000000000 000:00000   [ anon ]
00000000f7f30000       4 r---- 0000000000000000 008:00005 ld-2.31.so
00000000f7f31000     120 r-x-- 0000000000001000 008:00005 ld-2.31.so
00000000f7f4f000      44 r---- 000000000001f000 008:00005 ld-2.31.so
00000000f7f5b000       4 r---- 000000000002a000 008:00005 ld-2.31.so
00000000f7f5c000       4 rw--- 000000000002b000 008:00005 ld-2.31.so
00000000fff9c000     132 rw--- 0000000000000000 000:00000   [ stack ]
mapped: 2340K    writeable/private: 164K    shared: 0K

当然我们也可以换一个命令

➜  ~ cat /proc/33862/maps           
08048000-08049000 r--p 00000000 08:05 658197                             /home/lovetzp/Desktop/temp.out
08049000-0804a000 r-xp 00001000 08:05 658197                             /home/lovetzp/Desktop/temp.out
0804a000-0804b000 r--p 00002000 08:05 658197                             /home/lovetzp/Desktop/temp.out
0804b000-0804c000 r--p 00002000 08:05 658197                             /home/lovetzp/Desktop/temp.out
0804c000-0804d000 rw-p 00003000 08:05 658197                             /home/lovetzp/Desktop/temp.out
f7d25000-f7d3e000 r--p 00000000 08:05 569025                             /usr/lib/i386-linux-gnu/libc-2.31.so
f7d3e000-f7e99000 r-xp 00019000 08:05 569025                             /usr/lib/i386-linux-gnu/libc-2.31.so
f7e99000-f7f0d000 r--p 00174000 08:05 569025                             /usr/lib/i386-linux-gnu/libc-2.31.so
f7f0d000-f7f0e000 ---p 001e8000 08:05 569025                             /usr/lib/i386-linux-gnu/libc-2.31.so
f7f0e000-f7f10000 r--p 001e8000 08:05 569025                             /usr/lib/i386-linux-gnu/libc-2.31.so
f7f10000-f7f11000 rw-p 001ea000 08:05 569025                             /usr/lib/i386-linux-gnu/libc-2.31.so
f7f11000-f7f14000 rw-p 00000000 00:00 0 
f7f28000-f7f2a000 rw-p 00000000 00:00 0 
f7f2a000-f7f2e000 r--p 00000000 00:00 0                                  [vvar]
f7f2e000-f7f30000 r-xp 00000000 00:00 0                                  [vdso]
f7f30000-f7f31000 r--p 00000000 08:05 569021                             /usr/lib/i386-linux-gnu/ld-2.31.so
f7f31000-f7f4f000 r-xp 00001000 08:05 569021                             /usr/lib/i386-linux-gnu/ld-2.31.so
f7f4f000-f7f5a000 r--p 0001f000 08:05 569021                             /usr/lib/i386-linux-gnu/ld-2.31.so
f7f5b000-f7f5c000 r--p 0002a000 08:05 569021                             /usr/lib/i386-linux-gnu/ld-2.31.so
f7f5c000-f7f5d000 rw-p 0002b000 08:05 569021                             /usr/lib/i386-linux-gnu/ld-2.31.so
fff9c000-fffbd000 rw-p 00000000 00:00 0                                  [stack]

也可以得到内存映射关系。

从内存的分布中我们可以找到栈区,以及动态链接的一些库,以及头部的五个来自temp.out的区,这个内存映射分布与我们图并不是那么一致,是因为操作系统在处理segment段的时候,有自己的一些理解在里面,具体的就得看操作系统的实现了。

而且我们没有发现有堆区,这个我们可以在程序中加一个malloc,再看一下内存布局就有了。
库,以及头部的五个来自temp.out的区,这个内存映射分布与我们图并不是那么一致,是因为操作系统在处理segment段的时候,有自己的一些理解在里面,具体的就得看操作系统的实现了。

而且我们没有发现有堆区,这个我们可以在程序中加一个malloc,再看一下内存布局就有了。

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

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

相关文章

复习javascript第1章

JavaScript 是全球最流行的编程语言。 JavaScript 是属于 Web 的编程语言。 JavaScript 很容易学习。 JavaScript 能够改变 HTML 内容 getElementById() 是多个 JavaScript HTML 方法之一。 本例使用该方法来“查找” id"demo" 的 HTML 元素&#xff0c;并把元素…

深入浅出设计模式 - 迭代器模式

博主介绍&#xff1a; ✌博主从事应用安全和大数据领域&#xff0c;有8年研发经验&#xff0c;5年面试官经验&#xff0c;Java技术专家✌ Java知识图谱点击链接&#xff1a;体系化学习Java&#xff08;Java面试专题&#xff09; &#x1f495;&#x1f495; 感兴趣的同学可以收…

ERR_SSL_VERSION_OR_CIPHER_MISMATCH

Firefox开启TLS 1.1支持 问题&#xff1a; 建立安全连接失败 连接到…时发生错误。对等端使用了不支持的安全协议版本。 错误代码&#xff1a;SSL_ERROR_UNSUPPORTED_VERSION 由于不能验证所收到的数据是否可信&#xff0c;无法显示您想要查看的页面。 建议向此网站的管理…

Ubuntu TensorRT安装

文章目录 1.1环境1.2下载地址1&#xff09;操作步骤2&#xff09;添加环境变量3&#xff09;检查是否安装成功 2.1其它环境 1.1环境 1&#xff09;Ubuntu20.04 2&#xff09;cuda111torch1.8.0py38 1.2下载地址 https://developer.nvidia.com/nvidia-tensorrt-download 1…

【Linux】线程同步(一)

概念 线程同步是指多个线程之间协调和管理彼此的执行顺序&#xff0c;以避免竞态条件和不确定的结果。线程同步的目的是确保共享资源的正确访问和保护临界区的完整性。 作用 避免竞态条件&#xff1a;当多个线程同时访问和修改共享资源时&#xff0c;可能会导致竞态条件的发生…

javaee session的创建

当访问服务器时&#xff0c;服务器就会创建一个session TestSession.java package com.yyy.servlet;import java.io.IOException; import javax.servlet.ServletException; import javax.servlet.annotation.WebServlet; import javax.servlet.http.HttpServlet; import java…

String、反射、枚举、lambda表达式以及泛型进阶(数据结构系列16)

目录 前言&#xff1a; 1. String 1.1 字符串常量池 1.1.1 创建对象的思考 1.1.2 字符串常量池&#xff08;StringTable&#xff09; 1.1.3 再谈String对象创建 1.1.4 intern方法 2. 反射 2.1 反射的定义 2.2 反射的用途 2.3 反射的基本信息 2.4 反射相关的类 2.4.…

Android实现发送短信功能

Android发送短信 效果图代码实现先添加权限.java由用户输入手机号 自定义短信内容跳转系统发送短信页面 自定义手机号短信内容全部代码 .xml 效果图 代码实现 先添加权限 <!-- 允许程序发送SMS短信 --><uses-permission android:name"android.permission.SEND_S…

nodejs线上环境远程调试

将nodejs部署到线上环境之后&#xff0c;这个时候想要去调试还是有点困难的&#xff0c;但是好在nodejs提供了一个可以让你进行调试的开关&#xff1a;--inspect 我们可以使用这个开关来启动一个可以调试的服务&#xff0c;使用非常简单&#xff0c;在启动服务的时候加上这个指…

高性能计算怎么入门?

如果入门没有专业方向&#xff0c;自学摸索的话&#xff0c;不容易有自己的核心竞争力。国内目前生态尚不完善&#xff0c;学习资料也比较少~如果想要系统学习的话&#xff0c;一定不要错过国内首家专业做高性能计算的系统学习课程。 ~我们是国内首家做高性能计算人才培养和推…

微型逆变器会不会迎来CC2340时代

光伏领域的朋友对微型逆变器并不陌生。而CC2340&#xff0c;对大家而言则都是陌生的主。它是何方神仙&#xff1f;和微型逆变器能有什么关系&#xff1f;你还说它可能引领微型逆变器的下一个时代&#xff1f;不急&#xff0c;我们一起来看看。 在全球为双碳愿景努力以及俄乌战…

VR虚拟展会——打造商企展厅线上展示新模式

近期的大雨磅礴&#xff0c;不知道大家都感受过吗&#xff1f;就连在武汉展开的国际连锁加盟展产业博览会也都受到了一定的影响&#xff0c;为期三天的展会&#xff0c;接连下了三天的雨&#xff0c;导致很多客户无缘展会。这就是实体展会的限制之一&#xff0c;加上实体展会的…

vscode修改markdown侧边预览pdf字体等设置

文章目录 1.按CtrlShiftP打开命令窗口2.在命令窗口出输入Markdown Preview Enhanced: Customize Css&#xff0c;打开style.less文件 1.按CtrlShiftP打开命令窗口 2.在命令窗口出输入Markdown Preview Enhanced: Customize Css&#xff0c;打开style.less文件 然后在文件内加…

【网站维护】网络杂谈(7)之web网站的维护

涉及知识点 如何进行web网站的维护&#xff0c;如何进行web网站的更新与测试&#xff0c;搭建web网站后期如何管理维护。 原创于&#xff1a;CSDN博主-《拄杖盲学轻声码》&#xff0c;更多内容可去其主页关注下哈&#xff0c;不胜感激 文章目录 涉及知识点前言1&#xff0e;网…

仿牛客社区——7.19生成长图

采用异步方式&#xff0c;通过任务方式&#xff0c;将次命令丢到消息队列中进行执行 关于wkhtmltopdf的配置&#xff08;applaction.properties&#xff09; #关于wk的配置&#xff08;生成长图 wk.image.commandD:/wkhtmltopdf/bin/wkhtmltoimage wk.image.storageD:/wkData/w…

婴儿摇篮音乐芯片 N9300-S16:为宝宝带来高品质的音乐体验

​对于父母来说&#xff0c;给婴儿提供一个安稳舒适的睡眠环境是至关重要的。宝宝的睡眠品质对于其健康和发展至关重要。在成长过程中&#xff0c;音乐对婴儿的情绪、认知和智力发展都有积极的影响。因此&#xff0c;厂家在婴儿摇篮中选择一款合适的婴儿摇篮音乐芯片尤为重要。…

共见·价值成就|亚马逊云科技中国峰会宣布三大举措全面升级

2023年6月27日&#xff0c;亚马逊云科技举办一年一度的中国合作伙伴峰会。本届峰会以“共见价值成就”为主题&#xff0c;面向合作伙伴发布智荟出海计划、可持续发展伙伴计划、合作伙伴解决方案工厂以及获客激励计划等多项计划&#xff0c;以进一步强化合作伙伴“33战略”&…

ASEMI代理ST可控硅BTA16的工作原理与应用分析

编辑-Z 本文将对可控硅BTA16的工作原理与应用进行详细的分析。首先&#xff0c;我们将介绍可控硅BTA16的基本概念和工作原理&#xff0c;然后&#xff0c;我们将探讨其在电力电子设备中的应用&#xff0c;接着&#xff0c;我们将分析其在电力调节中的作用&#xff0c;最后&…

edge自带断网游戏

在没有网络时你会不会很无聊&#xff1f;博主告诉你一个edge浏览器自带的断网小游戏&#xff0c;让你在断网时也能玩游戏&#xff01; 网址&#xff1a; 打开edge://surf这个断网游戏网站即可游玩&#xff1a; 作弊码既隐藏模式&#xff1a; 输入microsoft&#xff08;意思就…

C语言学习(二十八)---字符串相关函数

在上一节的内容结束后&#xff0c;有关指针的内容就告一段落了&#xff0c;指针是开发中非常重要的一环&#xff0c;大家务必要对其深入理解并且掌握&#xff0c;今天我们将继续往下学习&#xff0c;主要学习字符串操作相关的函数&#xff0c;分为不限制长度和限制长度两种&…