运行时程序的机器指令存储在哪里?
Where machine instructions of a program stored during runtime?
据我所知,每当我们运行任何程序时,程序的机器指令都会加载到RAM中。同样,有两个内存区域:堆栈和堆。
我的问题是:机器指令存储在内存的哪个区域?堆栈还是堆?
我了解到下面的程序给出了 运行time 错误,尽管函数内部没有声明变量。这背后的原因是堆栈溢出。那我应该假设函数的机器指令存储在堆栈中吗?
int func()
{
return func();
}
都不是,因为它不是动态分配堆栈和堆的方式。
可执行文件加载器将可执行文件 (.text) 及其包含的任何静态数据(如全局变量 (.data / .rodata) 的初始值)加载到未使用的 RAM 区域。然后它设置可执行文件要求的任何零初始化内存 (.bss)。
只有然后是为main()
设置的堆栈。如果您输入另一个函数,堆栈内存将在堆栈上分配,保存 return 地址、函数参数和任何本地声明的变量以及通过 alloca()
分配的任何内存。[1]当您从函数中 return 时释放内存。
堆内存由malloc()
、calloc()
或realloc()
分配。当您 free()
或 realloc()
时它会被释放。
用于可执行文件及其静态数据的 RAM 在进程终止之前不会被释放。
因此,栈和堆基本上都在应用程序的控制之下。可执行文件本身的内存在可执行加载程序/操作系统的控制之下。在配备适当的操作系统中,您甚至没有对该内存的写入权限。
关于您编辑的问题,没有。 (糟糕的风格,编辑一个问题给它一个全新的角度。)
可执行代码保留在加载的位置。 调用函数不会将机器指令放入堆栈。你的func()
(一个不带参数的函数)唯一放在堆栈上的是return地址,一个指示一旦当前执行应该继续执行的指针函数 returns.
自从 none 次调用以来 return 秒,您的程序一直在堆栈上添加 return 个地址,直到无法容纳为止。这与机器代码指令完全无关。
[1]:请注意,none 实际上是 C 语言标准的重要组成部分,但是 实现定义的 ,并且可能有所不同——我呈现了事务的简化版本。例如,函数参数可能在 CPU 寄存器中传递,而不是在堆栈中传递。
既不是堆也不是栈。
通常,可执行指令存在于Code segment。
引用维基百科文章
In computing, a code segment, also known as a text segment or simply as text, is a portion of an object file or the corresponding section of the program's virtual address space that contains executable instructions.
和
when the loader places a program into memory so that it may be executed, various memory regions are allocated (in particular, as pages)
在运行时,目标文件的代码段被加载到内存中相应的代码段中。特别是,它与堆栈或堆无关。
编辑:
在您上面的代码片段中,您遇到的是所谓的无限递归。
即使您的函数不需要任何 space 堆栈中的局部变量,它 仍然需要 push return在调用 inner 函数之前,outer 函数的地址,从而声明堆栈 space,只是永远不会 return
[弹出地址出栈] [像在没有return的地方],因此运行出栈space,导致栈溢出
两者都不是。
您的程序映像包含代码和静态数据(f.e。所有字符串常量、静态数组和结构等)。它们将被加载到 RAM 的不同部分。
栈和堆是存储数据的动态结构,它们将在您的程序开始时创建。 Stack是硬件支持的解决方案,而heap是标准库支持的解决方案。
因此,您的代码将位于代码段,您的静态数据和堆将位于数据段,堆栈将位于堆栈段。
Again, there is two regions of memory: stack and heap.
没那么简单。通常在主流操作系统上会发生更多事情:
- 每个 运行 线程有一个堆栈;
- 你决定分配多少堆(实际上,就内存管理器而言,你在你的虚拟地址 space 中请求一些内存页到 "enabled", "heap" 事情源于这样一个事实,即通常使用某种堆管理器代码在分配之间有效地分配这些内存部分);
- 可以有内存映射文件和共享内存;
- 最重要的是,可执行文件(和动态库)映射到进程的内存中,通常以只读模式映射代码区(所谓的 "text" 段),并且写时复制中的其他区域(通常与初始化的全局和静态变量以及加载程序修复的内容有关)。
因此,代码存储在可执行文件的相关部分,并映射到内存中。
它们通常位于名为 .text
的部分。
在 Linux 上,您可以使用来自 core-utils 的 size
命令列出 ELF 对象或可执行文件的部分,例如在 tst
ELF 可执行文件上:
$ size -Ax tst | grep "^\.text"
.text 0x1e8 0x4003b0
$
the machine instructions of the program is loaded in RAM
适用于托管的 "PC-like" 系统。在嵌入式系统上,代码通常直接从闪存中执行
Again, there is two regions of memory: stack and heap.
不,这过于简单化了,编程老师教的太多了,太糟糕了。
还有很多其他区域:.data
和 .bss
所有具有静态存储的变量所在的位置,.rodata
常量所在的位置,等等。
存放程序代码的段通常称为.text
.
除了栈和堆之外,还有多个内存段。下面是程序在内存中的布局示例:
+------------------------+
high address | Command line arguments |
| and environment vars |
+------------------------+
| stack |
| - - - - - - - - - - - |
| | |
| V |
| |
| ^ |
| | |
| - - - - - - - - - - - |
| heap |
+------------------------+
| global and read- |
| only data |
+------------------------+
| program text |
low address | (machine code) |
+------------------------+
详细信息因平台而异,但这种布局对于基于 x86 的系统来说非常普遍。机器码占用自己的内存段(ELF格式标记为.text
),全局只读数据将存储在另一个段(.rdata
或.rodata
),未初始化的全局变量在另一个segment (.bss
) 等。有些段是只读的,有些是可写的。
据我所知,每当我们运行任何程序时,程序的机器指令都会加载到RAM中。同样,有两个内存区域:堆栈和堆。
我的问题是:机器指令存储在内存的哪个区域?堆栈还是堆?
我了解到下面的程序给出了 运行time 错误,尽管函数内部没有声明变量。这背后的原因是堆栈溢出。那我应该假设函数的机器指令存储在堆栈中吗?
int func()
{
return func();
}
都不是,因为它不是动态分配堆栈和堆的方式。
可执行文件加载器将可执行文件 (.text) 及其包含的任何静态数据(如全局变量 (.data / .rodata) 的初始值)加载到未使用的 RAM 区域。然后它设置可执行文件要求的任何零初始化内存 (.bss)。
只有然后是为main()
设置的堆栈。如果您输入另一个函数,堆栈内存将在堆栈上分配,保存 return 地址、函数参数和任何本地声明的变量以及通过 alloca()
分配的任何内存。[1]当您从函数中 return 时释放内存。
堆内存由malloc()
、calloc()
或realloc()
分配。当您 free()
或 realloc()
时它会被释放。
用于可执行文件及其静态数据的 RAM 在进程终止之前不会被释放。
因此,栈和堆基本上都在应用程序的控制之下。可执行文件本身的内存在可执行加载程序/操作系统的控制之下。在配备适当的操作系统中,您甚至没有对该内存的写入权限。
关于您编辑的问题,没有。 (糟糕的风格,编辑一个问题给它一个全新的角度。)
可执行代码保留在加载的位置。 调用函数不会将机器指令放入堆栈。你的func()
(一个不带参数的函数)唯一放在堆栈上的是return地址,一个指示一旦当前执行应该继续执行的指针函数 returns.
自从 none 次调用以来 return 秒,您的程序一直在堆栈上添加 return 个地址,直到无法容纳为止。这与机器代码指令完全无关。
[1]:请注意,none 实际上是 C 语言标准的重要组成部分,但是 实现定义的 ,并且可能有所不同——我呈现了事务的简化版本。例如,函数参数可能在 CPU 寄存器中传递,而不是在堆栈中传递。
既不是堆也不是栈。
通常,可执行指令存在于Code segment。
引用维基百科文章
In computing, a code segment, also known as a text segment or simply as text, is a portion of an object file or the corresponding section of the program's virtual address space that contains executable instructions.
和
when the loader places a program into memory so that it may be executed, various memory regions are allocated (in particular, as pages)
在运行时,目标文件的代码段被加载到内存中相应的代码段中。特别是,它与堆栈或堆无关。
编辑:
在您上面的代码片段中,您遇到的是所谓的无限递归。
即使您的函数不需要任何 space 堆栈中的局部变量,它 仍然需要 push return在调用 inner 函数之前,outer 函数的地址,从而声明堆栈 space,只是永远不会 return
[弹出地址出栈] [像在没有return的地方],因此运行出栈space,导致栈溢出
两者都不是。
您的程序映像包含代码和静态数据(f.e。所有字符串常量、静态数组和结构等)。它们将被加载到 RAM 的不同部分。
栈和堆是存储数据的动态结构,它们将在您的程序开始时创建。 Stack是硬件支持的解决方案,而heap是标准库支持的解决方案。
因此,您的代码将位于代码段,您的静态数据和堆将位于数据段,堆栈将位于堆栈段。
Again, there is two regions of memory: stack and heap.
没那么简单。通常在主流操作系统上会发生更多事情:
- 每个 运行 线程有一个堆栈;
- 你决定分配多少堆(实际上,就内存管理器而言,你在你的虚拟地址 space 中请求一些内存页到 "enabled", "heap" 事情源于这样一个事实,即通常使用某种堆管理器代码在分配之间有效地分配这些内存部分);
- 可以有内存映射文件和共享内存;
- 最重要的是,可执行文件(和动态库)映射到进程的内存中,通常以只读模式映射代码区(所谓的 "text" 段),并且写时复制中的其他区域(通常与初始化的全局和静态变量以及加载程序修复的内容有关)。
因此,代码存储在可执行文件的相关部分,并映射到内存中。
它们通常位于名为 .text
的部分。
在 Linux 上,您可以使用来自 core-utils 的 size
命令列出 ELF 对象或可执行文件的部分,例如在 tst
ELF 可执行文件上:
$ size -Ax tst | grep "^\.text"
.text 0x1e8 0x4003b0
$
the machine instructions of the program is loaded in RAM
适用于托管的 "PC-like" 系统。在嵌入式系统上,代码通常直接从闪存中执行
Again, there is two regions of memory: stack and heap.
不,这过于简单化了,编程老师教的太多了,太糟糕了。
还有很多其他区域:.data
和 .bss
所有具有静态存储的变量所在的位置,.rodata
常量所在的位置,等等。
存放程序代码的段通常称为.text
.
除了栈和堆之外,还有多个内存段。下面是程序在内存中的布局示例:
+------------------------+
high address | Command line arguments |
| and environment vars |
+------------------------+
| stack |
| - - - - - - - - - - - |
| | |
| V |
| |
| ^ |
| | |
| - - - - - - - - - - - |
| heap |
+------------------------+
| global and read- |
| only data |
+------------------------+
| program text |
low address | (machine code) |
+------------------------+
详细信息因平台而异,但这种布局对于基于 x86 的系统来说非常普遍。机器码占用自己的内存段(ELF格式标记为.text
),全局只读数据将存储在另一个段(.rdata
或.rodata
),未初始化的全局变量在另一个segment (.bss
) 等。有些段是只读的,有些是可写的。