双口ram存储器
当您运行任何C程序时,其可执行映像都会以有组织的方式加载到计算机的RAM中,这称为C程序的进程地址空间或内存布局。 在这里,我试图分两部分向您展示同一件事。
/!\:最初发布于 www.vishalchovatiya.com 。
在第1部分(即“概述”)中,我们将看到逐段概述;在第2部分(即“示例”)中,我们将看到C程序如何存储在RAM存储器中? 举个例子。
第1部分:概述
C程序的内存布局以下列方式组织:
注意:不仅仅是这4个部分,还有很多,但是这4个部分是了解C程序在机器级别上工作的核心。
HIGHER ADDRESS
+------------------------+
| Unmapped or reserved | Command-line argument & Environment variables
|------------------------|------------------------
| Stack segment | |
| | | | Stack frame
| v | v
| |
| ^ | ^
| | | | Dynamic memory
| Heap segment | |
|------------------------|------------------------
| Uninitialized data |
|------------------------| Data segment
| Initialized data |
|------------------------|------------------------
| |
| Text segment | Executable code
| |
+------------------------+
LOWER ADDRESS
main()
也是),包括用户定义的函数和系统函数。 本部分有两个小节
1.初始化数据
char string[ ] = "hello world"
定义的全局字符串以及在main
(即global)之外的int count=1
类的语句将存储在初始化的读写区域中。 const int A=3
这样的全局语句; 使变量A
只读,并存储在初始化的只读区域中。 2.未初始化的数据(BSS段)
int A
的全局变量将存储在未初始化的数据段中。 诸如static int X=0
类的语句也将存储在此段中,因为它初始化为零。 /lib/ld-linux.so.2
)。 malloc()
, calloc()
, realloc()
和C ++的new
分配)驻留的区域。 free()
或delete
)。 释放的内存返回到堆,但不必返回到操作系统(根本不必返回),因此无序malloc
/ free
最终会导致堆碎片。 您可以在此处了解有关malloc的更多信息。 main()
中声明的所有那些变量。 我在这里写了一篇关于函数堆栈框架的详细文章。 第2部分:示例
我们已经举了一个简单的例子,如标题以及其内存布局所示。 正如我们在上一部分(即概述)中所讨论的,程序的可执行映像如何划分为不同的段并存储在内存(RAM)中。 现在,我们通过使用上面提供的示例代码来理解这些块。
装载机
$ readelf --segments ./a.out
Elf file type is EXEC (Executable file)
Entry point 0x8048300
There are 9 program headers, starting at offset 52
Program Headers:
Type Offset VirtAddr PhysAddr FileSiz MemSiz Flg Align
PHDR 0x000034 0x08048034 0x08048034 0x00120 0x00120 R E 0x4
INTERP 0x000154 0x08048154 0x08048154 0x00013 0x00013 R 0x1
[Requesting program interpreter: /lib/ld-linux.so.2]
LOAD 0x000000 0x08048000 0x08048000 0x00608 0x00608 R E 0x1000
LOAD 0x000f08 0x08049f08 0x08049f08 0x00118 0x00124 RW 0x1000
DYNAMIC 0x000f14 0x08049f14 0x08049f14 0x000e8 0x000e8 RW 0x4
NOTE 0x000168 0x08048168 0x08048168 0x00020 0x00020 R 0x4
GNU_EH_FRAME 0x0004c4 0x080484c4 0x080484c4 0x00044 0x00044 R 0x4
GNU_STACK 0x000000 0x00000000 0x00000000 0x00000 0x00000 RW 0x10
GNU_RELRO 0x000f08 0x08049f08 0x08049f08 0x000f8 0x000f8 R 0x1
Section to Segment mapping:
Segment Sections...
00
01 .interp
02 .interp .note.ABI-tag .hash .dynsym .dynstr .gnu.version .gnu.version_r .rel.dyn .rel.plt .init .plt .plt.got .text .fini .rodata .eh_frame_hdr .eh_frame
03 .init_array .fini_array .jcr .dynamic .got .got.plt .data .bss
04 .dynamic
05 .note.ABI-tag
06 .eh_frame_hdr
07
08 .init_array .fini_array .jcr .dynamic .got
.data
, .bss
, .text
等段。 但是堆栈段未显示为在运行时创建的,而是由OS(精确地是loader和kernel)决定的。 INTERP
定义了加载器的名称和路径,该加载器将通过读取这些段将当前的二进制映像加载到RAM中。 这是/lib/ld-linux.so.2.
编译C代码时,您将获得可执行映像(可以是.bin
, .exe
, .hex
, .out
或任何扩展名等任何形式)。 该可执行文件包含Binutils命令$ objdump -d <binary_name>
看到的文本段,如下所示:
.....
080483f1 <main>:
80483f1: 8d 4c 24 04 lea 0x4(%esp),%ecx
80483f5: 83 e4 f0 and $0xfffffff0,%esp
80483f8: ff 71 fc pushl -0x4(%ecx)
.....
这是可执行的指令,以只读段的形式存储在文本段中,并在需要时由进程共享。 CPU使用程序计数器和执行时在堆栈中创建的堆栈帧读取这些指令。 程序计数器指向要执行的指令的地址,该地址位于文本段中。
初始化数据段
const int x = 1
; 存储在只读区域中。 因此,您不能意外修改它。 char str[] = "Hi!";
& static int var = 0;
存储在读写区域中,因为我们没有使用像const这样的关键字,它使变量为只读。 未初始化的数据段
int i
声明为global的int i
会进入该存储区域,因为默认情况下它没有初始化或初始化为零。 malloc()
, calloc()
等函数来接近OS。 malloc()
函数分配1字节动态内存,并将其地址存储在指针ptr
以跟踪该内存或对其进行访问。 ptr
是main的局部变量,因此它位于main的堆栈框架中,但是它指向的内存在我用*ptr
显示的堆中。 main()
,它也是一个函数,因此,在执行时会为其创建堆栈框架。 尽管在这里我已经讨论了main之前调用的许多函数。 main()
堆栈框架是在函数func()
嵌套之前创建的。 func( )
执行覆盖其局部变量a,并且其堆栈帧将被破坏(在这里倒带是一个精确的词), main()
函数也是如此。 直观的常见问题解答
问:如何确定堆栈的生长方向?
答:简单...! 通过比较两个不同函数的局部变量的地址。
int *main_ptr = NULL ;
int *func_ptr = NULL ;
void func () { int a; func_ptr = &a; }
int main ()
{
int a; main_ptr = &a;
func();
(main_ptr > func_ptr) ? printf ( "DOWN\n" ) : printf ( "UP\n" );
return 0 ;
}
问:如何故意破坏堆栈?
答:损坏存储在堆栈帧中的SFR值。
void func ()
{
int a;
memset (&a, 0 , 100 ); // Corrupt SFR values stored in stack frame
}
int main ()
{
func();
return 0 ;
}
问:如何增加堆栈框架大小?
答: alloca()是答案。 GOOGLE一下,或看看这个 。
双口ram存储器
文章浏览阅读3.8k次,点赞9次,收藏28次。直接上一个工作中碰到的问题,另外一个系统开启多线程调用我这边的接口,然后我这边会开启多线程批量查询第三方接口并且返回给调用方。使用的是两三年前别人遗留下来的方法,放到线上后发现确实是可以正常取到结果,但是一旦调用,CPU占用就直接100%(部署环境是win server服务器)。因此查看了下相关的老代码并使用JProfiler查看发现是在某个while循环的时候有问题。具体项目代码就不贴了,类似于下面这段代码。while(flag) {//your code;}这里的flag._main函数使用while(1)循环cpu占用99
文章浏览阅读347次。idea shift f6 快捷键无效_idea shift +f6快捷键不生效
文章浏览阅读135次。Ecmacript 中没有DOM 和 BOM核心模块Node为JavaScript提供了很多服务器级别,这些API绝大多数都被包装到了一个具名和核心模块中了,例如文件操作的 fs 核心模块 ,http服务构建的http 模块 path 路径操作模块 os 操作系统信息模块// 用来获取机器信息的var os = require('os')// 用来操作路径的var path = require('path')// 获取当前机器的 CPU 信息console.log(os.cpus._node模块中有很多核心模块,以下不属于核心模块,使用时需下载的是
文章浏览阅读10w+次,点赞435次,收藏3.4k次。SPSS 22 下载安装过程7.6 方差分析与回归分析的SPSS实现7.6.1 SPSS软件概述1 SPSS版本与安装2 SPSS界面3 SPSS特点4 SPSS数据7.6.2 SPSS与方差分析1 单因素方差分析2 双因素方差分析7.6.3 SPSS与回归分析SPSS回归分析过程牙膏价格问题的回归分析_化工数学模型数据回归软件
文章浏览阅读7.5k次。如何利用hutool工具包实现邮件发送功能呢?1、首先引入hutool依赖<dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.7.19</version></dependency>2、编写邮件发送工具类package com.pc.c..._hutool发送邮件
文章浏览阅读867次,点赞2次,收藏2次。docker安装elasticsearch,elasticsearch-head,kibana,ik分词器安装方式基本有两种,一种是pull的方式,一种是Dockerfile的方式,由于pull的方式pull下来后还需配置许多东西且不便于复用,个人比较喜欢使用Dockerfile的方式所有docker支持的镜像基本都在https://hub.docker.com/docker的官网上能找到合..._docker安装kibana连接elasticsearch并且elasticsearch有密码
文章浏览阅读1.3w次,点赞57次,收藏92次。整理 | 郑丽媛出品 | CSDN(ID:CSDNnews)近年来,随着机器学习的兴起,有一门编程语言逐渐变得火热——Python。得益于其针对机器学习提供了大量开源框架和第三方模块,内置..._beeware
文章浏览阅读7.9k次。//// ViewController.swift// Day_10_Timer//// Created by dongqiangfei on 2018/10/15.// Copyright 2018年 飞飞. All rights reserved.//import UIKitclass ViewController: UIViewController { ..._swift timer 暂停
文章浏览阅读986次,点赞2次,收藏2次。1.硬性等待让当前线程暂停执行,应用场景:代码执行速度太快了,但是UI元素没有立马加载出来,造成两者不同步,这时候就可以让代码等待一下,再去执行找元素的动作线程休眠,强制等待 Thread.sleep(long mills)package com.example.demo;import org.junit.jupiter.api.Test;import org.openqa.selenium.By;import org.openqa.selenium.firefox.Firefox.._元素三大等待
文章浏览阅读3k次,点赞4次,收藏14次。Java软件工程师职位分析_java岗位分析
文章浏览阅读2k次。Java:Unreachable code的解决方法_java unreachable code
文章浏览阅读1w次。1、html中设置标签data-*的值 标题 11111 222222、点击获取当前标签的data-url的值$('dd').on('click', function() { var urlVal = $(this).data('ur_如何根据data-*属性获取对应的标签对象