【问题标题】:Can static storage (mostly data segment) cause segmentation fault?静态存储(主要是数据段)会导致分段错误吗?
【发布时间】:2011-07-12 18:26:35
【问题描述】:

static 存储在编译时决定。但是,考虑一下我们在函数中有很多延迟初始化的场景:

void foo ()
{
  static int a[1000];
}

我在这里讨论的不是编码实践,而是技术方面。由于执行了许多 其他函数,如 foo(),因此许多 static 变量将被引入数据段。

在为数据段分配空间时,编译器是否也会在帐户中进行延迟初始化。如果“否”,那么它会在代码执行时导致运行时出现分段错误吗? (当template 方法中有很多static 数据时,更有可能发生)。

【问题讨论】:

  • 选择一种语言。 C 和 C++ 是不同的。
  • @Tomalak,这对他们俩都适用。
  • @Tomalak 他的示例显然很好地属于 C 和 C++ 的公共子集。作为公共子集的一部分,人们希望两种情况下的答案都是相同的。
  • @iammilind:更多的观众是无关紧要的。重要的是它被正确标记,C 或 C++ 都没有任何数据段的概念,如果这样的东西甚至不再存在,它是一个特定于平台的东西,所有语言的所有编译器都需要它。
  • @DeadMG:但他们确实定义了静态持续时间对象的语义。

标签: x86 segmentation-fault lazy-initialization data-segment


【解决方案1】:

仅仅因为初始化是惰性的,分配不是。该标准要求所有的静态变量(包括局部变量)在程序开始前进行零初始化。事实上,静态意味着(在这种情况下):变量的空间在程序的整个生命周期中都存在。

【讨论】:

  • +1,但如果空间分配给所有static 变量,那么templates 怎么样。他们将如何分配空间。
  • @iammilind - 没有区别。编译器知道有多少模板被实例化,并且可以添加所需的空间。这一切都是在编译时确定的。
  • @iammilind:模板不会改变任何东西。模板在构建时被实例化,每次发生时你都会从中得到一个函数。就像你的foo()
  • @iammilind 可执行文件中没有模板。当一个模板被实例化时,它就变成了一个函数或一个类,就像任何其他函数或类(几乎)一样。
【解决方案2】:

1) 一件事不会有“很多”变量。函数/方法范围内的静态变量非常类似于全局变量。

2) 没有惰性初始化,因为很可能在应用程序启动期间初始化,以及所有其他全局变量。

3) 我看不出故障的原因

Read more about Static(C++)

编辑:删除关于归零的声明

【讨论】:

  • “将缓冲区归零”;具有静态存储的对象是零初始化的。
  • 呵呵,是的,我正在检查 VS2010。在旧版本的 VS 中并非总是如此
  • 应该是。如果不是,那么这是 VS 对语言的公然违反。并不是说我太惊讶了。
【解决方案3】:

由于执行了许多这样的 foo()s,因此许多静态变量将被引入数据段。

没有。你只会得到一个foo()::a。这就是重点。

编译器是否也会在帐户中进行延迟初始化,而 为数据段分配空间。如果'否'那么,它会导致 代码执行时运行时出现分段错误? (更多的 当模板方法中有大量静态数据时可能会发生)。

如果您有太多 static 对象,您似乎在询问 .data 部分是否会用完空间(因此进一步写入可能会导致损坏错误)。

好吧,如上所述,在编译时就知道静态存储需要多少空间(对于函数模板实例化也是如此)。您确实不会在每次调用该函数时获得更多foo()::a,因此没有运行时元素来确定需要多少空间。

【讨论】:

  • 如果我正确理解了这个问题,他问的是分配,而不是初始化。 (当然,他的示例没有任何初始化,除了静态变量中始终存在的零初始化。)
  • @James:啊哈,我想我现在明白了。
  • As many such foo()s are executed,我的意思是其他功能,例如foo();不仅仅是foo()
  • @iammilind:你的意思是里面有很多静态持续时间对象的函数?好吧,编译器/链接器也可以在构建时看到所有这些......
【解决方案4】:

简短回答:不,您不会出现段错误。

在下面的示例中,abcData segment 中,defx 在 BSS 中。

#include <iostream>

int abc = 123;
int def;

int foo (int i) {
    static int x (i);
    return x;
}

int main () {
    std :: cout << foo (100) << " " << foo (200);
}

此示例打印出“100 100”:函数范围 static 对象的初始化仅在第一次调用期间发生。

x 的存储与 def 之类的全局变量相同。

模板基本相同,除非foo 被模板参数化,每个实例化都会有一个x

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-12-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-05-12
    • 2012-06-15
    • 2022-01-06
    相关资源
    最近更新 更多