当前位置:  开发笔记 > 编程语言 > 正文

谁负责C++中的堆栈和堆?

如何解决《谁负责C++中的堆栈和堆?》经验,为你挑选了2个好方法。

这不是任何一个目的是什么的问题.相反,这是一个问题,谁或什么负责堆栈和堆的发明?

这些C++编译器的发明是什么?

操作系统是否指定RAM中指定为"堆栈"和"堆"的内存部分?

我很确定它们不是内置于硬件中但我可能是错的.

此外,编译器是否负责生成汇编代码,指定哪些本地或函数数据将存储在堆栈与CPU寄存器中?



1> Thomas Matth..:

谁或什么负责堆栈和堆的发明?

就发明堆栈和堆而言,您可以更好地搜索网络.这些概念已存在数十年.

这些C++编译器的发明是什么?

也许发明在这里是错误的术语.它们是数据结构.编译器和OS(如果存在)负责组织和利用存储器.

操作系统是否指定RAM中指定为"堆栈"和"堆"的内存部分?

这是操作系统特定的,可能因操作系统而异.有些操作系统会保留堆栈和堆区域,有些则不会.

在我正在进行的嵌入式系统中,有两个堆区:1)链接器中指定的区域,2)分配给OS的一部分内存.这两个区域都设置为零,所以我们没有任何堆.

堆栈区域由在初始化C语言运行时库之前运行的初始化代码设置.RTL代码也可以创建一些堆栈区域.我们的RTOS还创建堆栈区域(每个任务一个).

因此,没有一个区域称为堆栈.某些平台根本不使用堆栈概念(特别是那些内存容量受到严格限制的平台).

我很确定它们不是内置于硬件中但我可能是错的.

取决于硬件.简单且廉价的硬件仅分配RAM区域(读/写存储器).更复杂和昂贵的硬件可以为堆栈,堆,可执行文件和数据分配单独的区域.常量可以放入ROM(只读存储器,如Flash)中.没有支持所有内容的单一配置或单配置.台式电脑不同的动物小于嵌入式系统.

此外,编译器是否负责生成汇编代码,指定哪些本地或函数数据将存储在堆栈与CPU寄存器中?

任务可以在链接器或编译器中,也可以在两者中.
许多编译器工具链都使用堆栈和CPU寄存器.许多变量和数据可以在堆栈,寄存器,RAM或ROM中.编译器旨在充分利用平台的资源,包括内存和寄存器.

研究的一个很好的例子是编译器生成的汇编语言.另请查看链接器指令文件.寄存器或堆栈存储器的使用如此依赖于数据结构(和类型),它们对于不同的功能可能是不同的.另一个因素是可用的内存量和种类.如果处理器可用的寄存器很少,则编译器可以使用堆栈传递变量.较大的数据(不适合寄存器)可以在堆栈上传递或传递给数据的指针.这里列举的选项和组合太多了.

摘要

为了使C和C++语言非常可移植,许多概念被委托给实现(编译器/工具链).其中两个概念通常称为堆栈.C和C++语言标准使用简单模型作为语言环境.此外,还有诸如"托管"和"半托管"之类的术语,表示平台支持语言要求的程度.该都没有数据结构需要,以支持的语言由平台.它们确实有助于提高执行效率.

如果支持堆栈和堆,则它们的位置和管理是实现的责任(工具链).编译器可以自由使用它自己的内存管理功能或OS(如果存在).堆栈和堆的管理可能需要硬件支持(例如虚拟内存管理或分页;以及防护).堆栈不需要向堆增长.不需要堆栈以正方向增长.这些都取决于实现(工具链),他们可以实现和定位堆栈,无论他们喜欢什么. 注意:最有可能的是,它们不会将变量放在只读内存中,也不会将堆栈放在内存容量之外.



2> cadaniluk..:

这篇文章是关于x86上的32位Linux .我不了解其他架构/操作系统.

这些C++编译器的发明是什么?[OS]是否指定RAM中指定为"堆栈"和"堆"的内存部分?

堆或免费商店

程序有不同的部分,其中一部分是.data部分.动态内存分配通常使用brk系统调用(sbrk在其上构建)来实现.man brk说如下:

brk()sbrk()更改程序中断的位置,该程序中断定义了进程数据段的结束(即,程序中断是未初始化数据段结束后的第一个位置).增加程序中断会为进程分配内存; 减少休息时间会释放内存.

这意味着"堆"或"免费商店"实际上是该.data部分.

正如@kfx在对这个答案的评论中所说,没有标准声明malloc必须使用brk.使用的实现mmap也是可能的.来自man mmap:

mmap()函数应在进程的地址空间和内存对象之间建立映射.

这基本上意味着文件(Unix意识形态:"一切都是文件")被映射到内存中.

堆栈也在该.data部分并向下增长.从技术上讲,x86使您能够定义向下增长的堆栈段,但Linux不使用此功能.不知道为什么.

我很确定它们不是内置于硬件中但我可能是错的.

不,他们不是.段在OS的运行时设置,而不是存储在硬件中.


以下内容来自Linux 4.2.

当MBR跳转到引导加载程序并且引导程序已执行时,将执行此操作(路径为/arch/x86/boot/header.S):

# Normalize the start address
    ljmp    $BOOTSEG, $start2

start2:
    movw    %cs, %ax
    movw    %ax, %ds
    movw    %ax, %es
    movw    %ax, %ss
    xorw    %sp, %sp

所有这些段寄存器都在$BOOTSEG这里初始化,即0x7c0.sp设置为0x00.不,esp因为我们仍处于实模式!

在完成初始化之后,执行跳转到真实内核.段寄存器设置如下:

movw    $__BOOT_DS, %cx
movw    $__BOOT_TSS, %di

movl    %cr0, %edx
orb $X86_CR0_PE, %dl    # Protected mode
movl    %edx, %cr0

# Transition to 32-bit mode
.byte   0x66, 0xea      # ljmpl opcode
2:  .long   in_pm32         # offset
.word   __BOOT_CS       # segment
ENDPROC(protected_mode_jump)

.code32
.section ".text32","ax"
GLOBAL(in_pm32)
# Set up data segments for flat 32-bit mode
movl    %ecx, %ds
movl    %ecx, %es
movl    %ecx, %fs
movl    %ecx, %gs
movl    %ecx, %ss

段寄存器cs再次设置为内容.


此外,编译器是否负责生成汇编代码,指定哪些本地或函数数据将存储在堆栈与CPU寄存器中?

是.对于函数调用,有不同的调用约定:一些将它们的参数压入堆栈,一些将它们移动到寄存器中.
局部变量也可以用寄存器或堆栈实现.
未经优化的C编译器将参数压入堆栈,调用函数,然后将其弹出("stdcall"调用约定).
它们将堆栈用于局部变量,并与ebp寄存器结合使用.


`malloc`可以使用`mmap`或其他选项实现,不需要使用`brk`.
推荐阅读
wangtao
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有