11
struct MemBlock {

    char mem[1024];

    MemBlock operator*(const MemBlock &b) const {

        return MemBlock();
    }

} global;

void foo(int step = 0) {

    if (step == 10000)
    {
        global = global * MemBlock();
    }
    else foo(step + 1);
}

int main() {

    foo();
    return 0;
}

程序收到信号 SIGSEGV,分段错误。0x08048510 in foo (step=4000) at t.cpp:12 12 void foo(int step = 0) {

尽管尚未调用 MemBlock() 实例,但它似乎消耗了大量的堆栈内存(检查 gdb 信息)。

而当我改用时global = global * global,程序正常退出。

任何人都可以解释内部机制吗?

4

1 回答 1

15

MemBlock编译器会在每次调用时为实例保留堆栈空间foo,而不管其中的控制流如何foo。这是一种常见的优化,可防止在函数内重复调整堆栈指针。相反,编译器计算所需的最大堆栈空间,并在进入函数时将堆栈指针调整该数量。

正如您所观察到的,这会导致丢失为您实际不使用的对象保留的堆栈空间。答案是不要那样做;如果您只在某些分支中使用一些大尺寸对象,那么将这些分支分离到它们自己的功能中。

Incidentally, this is why archaic versions of C required all function-scope variables to be declared at the top of the function; so that the compiler can easily work out how much stack space the function requires.

于 2012-07-20T12:29:05.747 回答