一个类对象可以持有多大的属性?如何确定堆栈/堆限制?

4

我有一个需要大量内存的类。

class BigClass {
public:
    BigClass() {
        bf1[96000000-1] = 1;
    }
    double bf1[96000000];
};

我只能通过在堆内存中“new”一个对象来启动类。
BigClass *c = new BigClass();
assert( c->bf1[96000000-1] == 1 );
delete c;

如果我在不使用 "new" 的情况下启动它,那么运行时将会出现分段错误。
BigClass c; // SIGSEGV!

我应该如何确定内存限制?还是说我最好始终使用“new”?

只是猜测,限制可能实际上来自程序运行时操作系统提供的堆。 - clamp
@clamp 你不应该混淆堆内存(由new运算符使用)和用于自动变量的栈内存,例如BigClass c; - Luca Martini
6个回答

3
首先,既然您将其命名为C++而不是C,为什么要使用数组?相反,我建议使用vector<double>或者如果连续内存引起问题,可以使用deque<double>,后者可以放宽对连续内存的约束,同时保持近乎恒定的时间查找。
使用vectordeque还可以缓解其他可能在以后困扰您项目的段错误问题。例如,在数组中超出边界。如果转换为使用vectordeque,您可以使用.at(x)成员函数来检索和设置集合中的值。如果尝试越界写入,该函数将抛出错误。

1
此外,如果使用 vector,如果您将使用大量内存,可能需要调用 vector::reserve - user470379
@user470379 说得好,但只有在需要执行 push_back 操作时才适用。我认为这里的大小将是静态的。 - wheaties
1
@wheaties,然而你的第二段似乎不太准确。导致分段错误最有可能的解释是单个BigClass实例比剩余的堆栈空间还要大。 - Jon-Eric
@Jon-Eric,你说得对。很可能是因为该项太大而无法放入堆栈中。我会将其移除。 - wheaties
@user470379,通常在您想要将更多项目附加到列表中而又避免复制旧向量连续数组到更新的较大版本时,使用reserve。在这里,似乎OP想要一个静态大小而不是动态大小的数组。向量允许您在构造函数调用中设置特定的大小。 - wheaties
显示剩余2条评论

2

栈的大小是固定的,这取决于编译器选项。请查阅编译器文档以更改可执行文件的堆栈大小。

无论如何,对于大型对象,最好使用new或更好的智能指针,例如shared_pointer(来自boost或std :: tr1或std ::,如果您有非常新的编译器)。


1

没有平台无关的方法来确定内存限制。对于“大量”内存,最安全的方式是在堆上分配(即使用new);您可以通过将结果指针与NULL进行比较或捕获std::bad_alloc异常来检查成功与否。


2
注意,根据使用的分配器,operator new 在失败时可能会抛出 bad_alloc 异常而不是返回 NULL。请参阅 C++ 规范,ISO/IEC 14882:2003(E) 第 5.3.4.13 节。 - Wyatt Anderson

1

你永远不应该玩那个游戏。你的代码可能会被从另一个函数中调用或在一个堆栈大小限制较低的线程上运行,然后你的代码将会出现严重错误。请参考这个紧密相关的问题

如果你有疑问,请使用堆分配(new)- 可以直接使用智能指针(如auto_ptr)或间接使用std::vector


1
你的类设计方式非常脆弱,正如你所发现的那样。不要总是在堆上分配对象,而是应该让你的类自己在堆上分配大内存块,最好使用std::vector,或者如果vector不能使用,则可能需要使用shared_ptr。然后你就不必担心客户端如何使用对象了,它可以安全地放在堆栈或堆上。

0
在Linux的Bash shell中,您可以使用ulimit -s检查堆栈大小。具有自动存储期限的变量将在堆栈上分配其空间。正如其他人所说,有更好的方法来处理这个问题:
  1. BigClass 内部使用 std::vector 存储数据。
  2. BigClass 的构造函数中为 bf1 分配内存,然后在析构函数中释放它。
  3. 如果你必须拥有一个大的 double[] 成员,则可以使用某种 智能指针 来分配 BigClass 的实例;如果不需要共享访问,那么像 std::auto_ptr 这样简单的东西就可以让你安全地构造/销毁对象:

    std::auto_ptr<BigClass>(new BigClass) myBigClass;
    myBigClass->bf1; // 你的数组
    

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接