【问题标题】:What does sbrk(0) point to when initializing static variables?初始化静态变量时,sbrk(0) 指向什么?
【发布时间】:2020-12-15 14:36:14
【问题描述】:

sbrk(2) manual

它表明

调用sbrk(),增量为0,可用于查找 程序中断的当前位置。

sbrk(0) 用于初始化static 变量时,这是如何工作的?

说,

static void* current_heap = sbrk(0);

这种好奇心源于 C/C++ 代码的典型编译步骤在编译时确定数据段的大小。

如下图所示,

Distributed under CC BY-SA 3.0

初始化的静态变量存储在数据段中。据我所知,堆通常从 BSS 和数据段的末尾开始。

sbrk(0) 如何知道编译期间堆从哪里开始,而其他静态变量可能尚未确定?

更新:

正如@EugeneSh 所述,这是一个使用clang++ 编译的工作示例:

#include <unistd.h>
#include <iostream>

static void* current_heap = sbrk(0);

int main() {
  std::cout << current_heap << '\n';
}

【问题讨论】:

  • 你检查过它真的编译了吗?
  • @EugeneSh。我成功编译了包含命名空间下的变量的代码,该变量使用sbrk(0) 初始化。
  • 那么请发帖minimal reproducible example。我怀疑它可以编译(至少在 C 中)
  • 另一个你不应该询问 C/C++ 而是选择特定语言的原因。如您所见,这些是完全不同的野兽。
  • @EugeneSh.Right。我从帖子中删除了c 标签。

标签: c++ unix memory


【解决方案1】:

在 C 中,此代码无效:

static void* current_heap = sbrk(0);

因为具有静态存储持续时间的对象的初始化程序必须是编译时常量,而事实并非如此。所以这段代码将无法在 C 中编译。

对于 C++,当程序在调用 main 之前的某个时间点运行时,将调用该函数。

因此没有对sbrk 的编译时调用。

至于这个变量将驻留在哪个部分,它很可能在 .bss 中,因为它在编译时没有初始化。事实上,如果我用 g++ 编译你的代码,变量就会放在 .bss 中。

【讨论】:

  • 好的,我明白了。因此,在初始化时,所有static 变量都已确定。因此,sbrk(0) 的行为是预期的吗? (在 C++ 中)
  • @PHD 带有常量初始化器的静态变量放在 .data 中,而未初始化或非常量初始化的静态变量放在 .bss 中,sbrk 在程序执行时运行。
【解决方案2】:

根据 C 标准,6.7.9:

具有静态或线程存储持续时间的对象的初始化程序中的所有表达式都应为常量表达式或字符串文字。

因此这不是 C 中的有效初始化。

在 C++ 中,这将是一个运行时初始化。

【讨论】:

    猜你喜欢
    • 2012-02-01
    • 2019-12-23
    • 1970-01-01
    • 2023-03-22
    • 2019-09-22
    • 1970-01-01
    • 2011-08-22
    • 2010-12-22
    • 1970-01-01
    相关资源
    最近更新 更多