gpt4 book ai didi

c++ - 关于编译程序如何与操作系统交互的问题

转载 作者:塔克拉玛干 更新时间:2023-11-02 23:31:46 28 4
gpt4 key购买 nike

已经有一段时间了,我一直在用 C/C++ 编程,但有些领域仍然让我望而却步。也许我没有读过写得很好的权威 Material 。

(1) 在Linux/Unix 中,用户程序的大小是否有限制?程序可以拥有的最大堆栈大小?用户程序可以使用的堆中的最大内存量?

(2) 我了解 C 可执行文件具有数据部分、代码部分和堆栈部分。如果程序进入许多递归调用,它将需要大量堆栈。这个堆栈是预定义的大小还是会随着递归的增加而增长。在增长的情况下,程序的地址空间是否也必须动态增加?如果是这样,那不会减慢程序的速度吗?

(3) 类似地,当程序mallocs时,堆中的内存在运行时分配给程序时,堆中的那部分区域是否需要添加到程序的地址空间?因此在这种情况下,程序的页表也需要更新。我的理解正确吗?

(4) 为什么 2 个文件(我打算将它们组合成一个可执行文件)不能有一个同名的全局变量。这有助于阐明目标文件的外观。

添加:

我正在阅读来自 http://www.open-std.org/jtc1/sc22/wg...docs/n1256.pdf 的 ISO C99 标准.它在第 42 页上说:

6.2.2 标识符的联系1 在不同作用域或同一作用域中多次声明的标识符可以是通过称为链接的过程来引用相同的对象或函数。有三种链接:外部链接、内部链接和无链接。

2 在构成整个程序的翻译单元和库集合中,每一个具有外部链接的特定标识符的声明表示相同的对象或功能。在一个翻译单元中,每个带有内部标识符的声明linkage 表示相同的对象或函数。每个标识符的声明都没有linkage 表示一个唯一的实体。

3 如果对象或函数的文件范围标识符的声明包含存储类说明符 static,则标识符具有内部链接。

4 对于在一个范围内使用存储类说明符 extern 声明的标识符该标识符的先前声明是可见的,如果先前声明指定了内部或外部链接,则后面声明中标识符的链接与先前声明中指定的链接相同。如果没有可见的先前声明,或者如果先前声明未指定链接,则标识符具有外部链接。

5 如果函数标识符的声明没有存储类说明符,则其链接的确定就好像它是用存储类说明符 extern 声明的一样。如果对象的标识符声明具有文件范围并且没有存储类说明符,它的链接是外部的。

阅读本文后,看起来如果我在 2 个源文件中声明一个像 int a 这样的变量。然后根据规则 5 和 4 都具有外部链接。然后根据规则 2,两者都应该引用同一个对象。那为什么编译器会产生问题。在标准中暗示我们不能在 2 个源文件中这样声明,这应该会引发编译错误。

谢谢。

最佳答案

回答您的问题-

  1. 大多数操作系统使用虚拟内存让每个程序认为它拥有所有地址空间。这意味着通常对程序大小的限制是系统中的物理内存量减去通常为无效(想想 NULL)指针和内核保留的少量内存。最大内存限制通常与平台相关,但在 32 位系统上,您的程序通常可以获得近 4GB 的内存,而在 64 位系统上则多得多。当然,您还必须考虑磁盘的大小,这限制了您可以拥有多少虚拟内存。理论上,您可以编写一个大到无法放入内存的程序,但除非您使用的是嵌入式设备(这确实是一个问题),否则我怀疑这种情况永远不会发生。

  2. 在大多数编程语言中,包括 C 和 C++,堆栈大小在编译时并不固定,而是从小开始,然后随着程序运行而增长。然而,堆栈增长的方式通常使它变得特别便宜 - 要获得更多空间,您只需要稍微增加堆栈指针即可。如果这会将您带到当前未分配给程序的内存中,操作系统通常会通过将页面与堆栈现在所在的虚拟地址相关联来为您分配内存,这比进行堆分配要快得多。从长远来看,这样做的成本通常可以忽略不计,所以不要气馁使用堆栈内存。有趣的是,一些较旧的编程语言,即 FORTRAN 的第一个版本,没有动态堆栈空间,因此递归是不可能的。几乎所有现代语言都消除了这些限制。

  3. 您是对的 - 当需要更多堆空间时,通常会调整页表以增加堆空间。许多内存分配器选择将大部分内存放入匿名内存映射文件中,以避免为此目的直接使用堆空间,但原理本质上是相同的 - 更新页表以为新内存腾出空间。

  4. 如果您在不同的文件中有两个全局变量链接在一起,那么两个目标文件都将包含符号链接(symbolic link),表明它们需要引用具有该名称的变量,并且两个目标文件都将包含定义说他们提供了这个名字的符号。当您尝试将它们链接在一起时,链接器会注意到在两个地方定义了相同的符号名称,并且会报告错误,因为它不确定应该使用其中的哪一个作为该全局变量的“the”实例。为了解决这个问题,至少在 C 中,您可以将全局变量标记为 static 以赋予它们内部链接。这使得符号不会全局导出,因此生成的目标文件可以在内部解析引用或破坏名称,以便它不会与其他文件中的其他符号冲突。 C++ 允许这一点以及匿名命名空间功能来实现相同的效果。

希望对您有所帮助!如果有人在这里发现错误或含糊之处,请告诉我,我很乐意纠正它们。

关于c++ - 关于编译程序如何与操作系统交互的问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/4989419/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com