静态数组仅在类定义内溢出堆栈(段错误 11),否则不会......?

Posted

技术标签:

【中文标题】静态数组仅在类定义内溢出堆栈(段错误 11),否则不会......?【英文标题】:Static array overflows stack (seg fault 11) only when inside class definition, but not otherwise...? 【发布时间】:2017-04-14 17:56:52 【问题描述】:

我想分配一个大的静态数组(--想避免动态分配,例如使用 std::vector,甚至使用'new',所以我可以保证物理地址是连续的并且可以预取有效地)。我的数组大小由外部因素决定,但它们是提前知道的——在这个例子中,我总是需要 3211264 个元素。

如果我只是分配一个浮点数组,一切正常:

    #include <iostream>
    #include <cstdlib>

    using namespace std;

    float f[3211264];

    int main()
    
      for(int i = 0; i < 3211264; i++) 
         f[i] = rand();

      for(int i = 0; i < 3211264; i++) 
         cout << f[i];
    

但是,如果我将数组包装在一个类中,则会导致 Seg 错误:

    #include <iostream>
    #include <cstdlib>

    using namespace std;

    class T
    
      public:
        T();

      private:
        float f[3211264];
    ;


    T::T()
    
        for(int i = 0; i < 3211264; i++)
            f[i] = rand();

        for(int i = 0; i < 3211264; i++)
            cout << f[i];

    

    int main()
    
        T myT;
    

这个内存是如何分配的,当我将数据包装在一个类中时,它有什么不同的原因吗?

我希望类开销最小,并且任何基于对象的重新对齐或填充最多只能是页面侧(4K),对吗?对我来说,这个类主要是为了可读性和组织性,但如果它会对性能产生重大影响,我会放弃它并声明一堆全局变量......

我的编译器信息:

配置为:--prefix=/Applications/Xcode.app/Contents/Developer/usr --with-gxx-include-dir=/usr/include/c++/4.2.1

Apple LLVM 版本 7.3.0 (clang-703.0.29)

目标:x86_64-apple-darwin15.6.0

线程模型:posix

【问题讨论】:

什么是sizeof(T);?取该值并确定您的程序有多少可用的堆栈空间。 在第一个示例中,f 在堆栈中。这就是它不超过堆栈的原因。 数组的元素在内存中是连续的,即使是动态分配的。 在连续点上:仅适用于虚拟地址,而不是物理地址,这是硬件预取器关心的... float f[3211264] 的大小为 12.25 MB。静态内存可以处理那么多数据。堆栈内存不能,除非您在链接器设置中调整堆栈大小。 【参考方案1】:

在将数组设为类成员的代码中,它不是静态分配的。如果你说:

static T myT;

虽然我不敢相信静态分配它会给你带来任何显着的性能提升。

【讨论】:

以上是关于静态数组仅在类定义内溢出堆栈(段错误 11),否则不会......?的主要内容,如果未能解决你的问题,请参考以下文章

递归 - 堆栈溢出错误

创建大型数组时,线程“<main>”已溢出其堆栈

在发生堆栈溢出之前剩余堆栈的大小

找出哪个对象/数组使用最多的堆栈内存

Nginx - 仅在静态文件上出现403错误

堆栈溢出 - 静态内存与动态内存