共享库和可执行文件与 Linux 上的静态 C 运行时链接.它们中的每一个都有像Windows这样的独立堆吗?
Shared Libraries and Executable linking with static C run time on Linux. Does each of them have separate heap like Windows?
我很清楚窗口堆分配和堆堆栈等。虽然是 Linux 的新手,但我不太清楚它是如何工作的?
在视窗上:
- 在进程开始时,OS 会创建一个名为"进程堆"的默认堆。进程堆用于在没有使用其他堆的情况下分配块。
- 语言运行时还可以在进程中创建单独的堆。(例如,C 运行时创建自己的堆。
- 除了这些专用堆之外,应用程序或许多加载的动态链接库 (DLL) 之一可以创建和使用单独的堆,称为专用堆
- 这些堆位于所有虚拟内存系统中操作系统的虚拟内存管理器之上。
- a) C/C++ 运行时 (CRT) 分配器:提供 malloc() 和 free() 以及 new 和 delete 运算符。b) CRT 为其所有分配创建这样一个额外的堆(此 CRT 堆的句柄存储在 CRT 库内部名为 _crtheap 的全局变量中),作为其初始化的一部分。c) CRT 创建自己的专用堆,该堆驻留在 Windows 堆之上。d) Windows 堆是围绕 Windows 运行时分配器 (NTDLL) 的薄层。e) Windows 运行时分配器与虚拟内存分配器交互,虚拟内存分配器保留并提交操作系统使用的页面。
我们的 DLL 和 exe 链接到多线程静态 CRT 库。我们创建的每个 DLL 和 exe 都有自己的堆,即 _crtheap。分配和取消分配必须从各自的堆中进行。从 DLL 动态分配,不能从可执行文件中取消分配,反之亦然。
使用/MD 或/MDd 在 DLL 和 exe 中编译我们的代码以使用特定于多线程和特定于 DLL 的运行时库版本,会将 DLL 和 exe 链接到同一个 C 运行时库,从而链接到一个_crtheap。分配始终与单个模块内的取消分配配对。
这是 Liunx 上的行为吗?堆都有哪些?CRT 堆呢?
我真的不知道如何回答这个问题,但我会尝试提供足够的一般信息,我会抓住你需要知道的。
作为一个Unix人,我从你的问题中学到的关于Windows内存管理的是,你们经常使用"堆"这个词。我们没有,除了作为"由malloc管理的内存区域"的非正式同义词。
需要注意 2 个主要的动态内存分配原语:brk
和 mmap
。所有其他分配功能(包括malloc
)都建立在这些功能之上。
brk
是旧的。它的工作原理是在 bss 段结束后简单地向进程的虚拟内存映射添加更多内存。你brk
传递一个值,它就成为进程的"中断"地址 - 分配的虚拟内存的末尾。
Malloc 可以构建在brk
之上,方法是在每次需要更多内存时用新的、更高的值调用它,并维护一些内部数据结构来跟踪已释放的内容和仍在使用的内容。(在经典实现中没有免费将内存返回给系统。某些 malloc 实现的内部数据结构一定是一个堆,给 brk 段起了昵称:"堆"。
另请参阅:brk( ) 系统调用有什么作用?(它有图片!
程序直接调用brk
真的很不寻常。(甚至是薄包装纸sbrk
)。在正常程序中每次使用brk
都是通过malloc
。请记住,虽然您将 C 库(包括 malloc
)视为某种可选的附加功能,但我们有一个与 C 紧密耦合的操作系统,因此不使用 libc 进行内存管理等低级操作的程序确实非常奇怪。所以大多数时候,brk段(又名"堆")中的所有内存都由malloc管理。但是,反之则不然,因为...
mmap
,比brk
更新(mmap来自90年代;brk来自70年代)提供了很多选择。如果要将文件映射到内存中,或分配多个不连续的内存块,而不仅仅是在原始数据块的末尾添加一些空间,请使用 mmap
。共享库加载程序使用 mmap 映射每个库的文本和数据。现代malloc实现将mmap用于大型请求,将brk用于小型请求。我们还有mremap
,它将映射重新定位到新的虚拟地址,同时将其保留在同一物理地址上,从而使 realloc 能够避免昂贵的副本。
如果你在 Linux 上查看/proc/$PID/maps
,你会看到一个标记为 [heap]
的内存区域。这就是BRK细分市场。每个进程只有一个。(我看过一些例子,其中maps
文件显示了其中的 2 个,但它们是连续的并且具有相同的属性,因此实际上相当于单个区域。我不知道是什么原因导致双重上市。
考虑到所有这些背景,分配"额外堆"意味着什么?您可以使用 mmap 从系统请求一些内存,从而为您提供一个独立于 malloc 的区域。然后,您可以对该区域进行自己的类似malloc的管理,将其分成各种大小的块分发,并跟踪哪些部分未使用。但是您的新分配器不会是"堆"。这实际上没有任何意义,因为系统对堆一无所知。
- 在 Windows 上,是否可以让 dll 在不使用 PATH 环境变量的情况下在另一个文件夹中查找依赖项?
- 如何创建一个所有行大小不同的 2D 数组,并且用户将指定每行将有多少个元素?
- 对于C++中的每一个都无法更新向量
- 如何从这些语句中的每一个创建不同的函数?
- 在C++中,系统如何将这些对象中的每一个与执行程序的窗口相关联?
- Windows,C++:一个服务器套接字上有两个连接
- 在整数C 中分开每一个数字
- 找不到正确的 Qt5Core.dll 文件。我发现的每一个都会给出不同的错误
- 为windows实现一个自定义的unistd.h来处理VisualStudio问题
- C++-是否可以使用random_shuffle生成数组的每一个排列,一次且仅一次
- 为Windows编写一个非阻塞stdin读取函数
- 为什么我的struct只存储最后一个字符串,而不是每一个
- 交叉编译从linux到windows的一个visual studio项目
- 在c++中,为什么ifstream getline返回我的.txt文件中的每一个数字,而不是所有的数字
- 为XP和Vista/Windows 7创建一个Win32应用程序
- 给定了在C++中返回对象的各种方法,这些返回语句中的每一个都有哪些潜在的问题
- 共享库和可执行文件与 Linux 上的静态 C 运行时链接.它们中的每一个都有像Windows这样的独立堆吗?
- 对于每一个奇怪的行为
- c++ Macro Magic:获取每一个宏参数,对参数计数
- 在Linux上为Windows构建一个应用程序