一个过深的C ++类层次结构会导致堆栈溢出吗?

时间:2012-01-18 18:03:30

标签: c++ stack stack-overflow distributed-computing callstack

假设我有一个C ++程序具有过深的继承,如下所示:

using namespace std;

class AbstractParentGeneration0 {
    private:
      ...
    protected:
      ...
    public:
      virtual returnVal funcName(void) = 0;
};

class AbstractParentGeneration1: virtual public AbstractParentGeneration0 {
    private:
      ...
    protected:
      ...
    public:
      virtual returnVal funcName(void) = 0;
};

.
.
.

class AbstractParentGeneration999999999: virtual public AbstractParentGeneration999999998 {
    private:
      ...
    protected:
      ...
    public:
      virtual returnVal funcName(void) = 0;
};

class ChildGeneration: public AbstractParentGeneration999999999 {
    private:
      ...
    protected:
      ...
    public:
      returnVal funcName(void) { ... };
};

假设程序的性质是深度继承 不能被压缩(假设它代表一个进化物种 血统或深层分类学层次结构)

调用顶级抽象类时是否存在堆栈溢出危险?

什么策略(除了“ulimit -s bytes”或者崩溃了 抽象层次结构)C ++程序员用来在其中工作 系统边界?

是否有办法在整个过程中展平深层垂直继承层次结构 许多主机系统通过RPC?

有些人设计自己的调用堆栈机制吗?

是否存在分布式网络/集群调用堆栈这样的事情?

5 个答案:

答案 0 :(得分:6)

很可能,这会违反编译器的一些内部约束。如果出现问题,您将看不到运行时。

解决此问题的一般方法是停止生成这样的代码。不要将这种数据烘焙到运行时。相反,这应该是一些文件格式,它被加载并解析为类实例的层次结构,而不是类本身。

答案 1 :(得分:5)

  

调用顶级抽象类时是否存在堆栈溢出危险?

肯定有。每个构造函数和析构函数都将调用父类中的对应项,一直到层次结构,生成一个非常深的调用堆栈。

如果它在构造中存活,那么调用虚函数就可以了 - 这只是对最终覆盖的单个函数调用。

  

C ++程序员使用什么策略(除了ulimit -a或折叠抽象层次结构)在系统边界内工作?

就个人而言,我倾向于完全避免继承(除了抽象接口,以及我懒得很好地封装东西的情况)。

在这种情况下,我可能会建议对象的运行时层次结构,可能使用函数指针来为虚函数提供类似的行为;唯一的限制是存储它们所需的内存。它不像使用类型系统来表示您的类别那样优雅,但不太可能遇到实现限制。

答案 2 :(得分:2)

要回答您的具体问题, no 在调用顶级抽象虚拟方法时,运行时不存在堆栈溢出的危险。大多数C ++实现都会在对象实例中有一个vtable指针条目,它直接指向适当的实现函数。

如果您对这是如何工作感到好奇,我建议您编写一个具有几个层次结构的程序,并加载一个程序集级调试器,向您显示实际情况。

答案 3 :(得分:1)

试试并亲自看看;)

template <int i>
class oferflowMe: public overflowMe<i-1>{
    ....
};

template <>
class oferflowMe<1>{
    ....
};

答案 4 :(得分:0)

不是在这个简单的情况下。但是,如果您有多个虚拟继承,那么一些编译器将使用“adjustor thunks”来修复this。这些小功能将最终出现在你的调用堆栈中。