C ++堆栈和作用域 [英] C++ stack and scope

查看:111
本文介绍了C ++堆栈和作用域的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

 我在Visual C ++ 2008上试过这个程式码,它显示A和B没有相同的地址。 int main()
{
{
int A;
printf(%p \\\
,& A);
}

int B;
printf(%p \\\
,& B);
}

但是因为A在定义B时不再存在,我不知道为什么编译器似乎没有做什么看起来像一个非常简单的优化(这是一个非常简单的优化)。可能在较大变量和递归函数的上下文中是重要的)。它似乎不再重用它会更重的CPU和内存。有没有人有这样的解释?



我想答案是沿着因为它比看起来复杂得多的线,但老实说,我不知道。



编辑:关于下面的答案和意见的一些准则。



与这段代码是每次这个函数被调用,堆栈增长一个整数太多。当然,这在示例中没有问题,但考虑大变量和递归调用,并且您有一个可以很容易避免的堆栈溢出。



我建议的是内存



顺便说一下,这种情况发生在发布版本中,所有优化on。

解决方案

为本地人重用堆栈空间是一个非常常见的优化。事实上,在一个优化的构建中,如果你没有获取本地的地址,编译器可能甚至不分配栈空间,变量只会存在一个寄存器。



您可能无法看到此优化的原因有几个。



首先,如果优化关闭(如调试版本),编译器将不会使调试更容易 - 即使它不再在函数中使用,您也可以查看A的值。



如果您正在使用优化进行编译,我的猜测是你正在获取本地的地址并将其传递给另一个函数,编译器不想重用该存储,因为它不清楚该函数正在做的地址。



还可以想象一个编译器不会使用这个优化,除非一个函数使用的堆栈空间超过某个阈值。我不知道有什么编译器这样做,因为重用不再使用的局部变量的空间是零成本,可以应用于所有。



如果堆栈增长是您的应用程序的一个严重问题,即在一些情况下,您正在击中堆栈溢出,您不应该依赖于编译器的堆栈空间的优化。您应该考虑将堆栈上的大缓冲区移动到堆上,并努力消除非常深的递归。例如,在Windows上,线程默认有1 MB的堆栈。如果你担心溢出,因为你在每个堆栈帧上分配1k的内存,并进行1000个递归调用,修复不是试图让编译器保存每个堆栈帧的一些空间。


I tried this code on Visual C++ 2008 and it shows that A and B don't have the same address.

int main()
{
    {
    	int A;
    	printf("%p\n", &A);
    }

    int B;
    printf("%p\n", &B);
}

But since A doesn't exist anymore when B gets defined, it seems to me that the same stack location could be reused...

I don't understand why the compiler doesn't seem to do what looks like a very simple optimization (which could matter in the context of larger variables and recursive functions for example). And it doesn't seem like reusing it would be heavier on the CPU nor the memory. Does anyone have an explanation for this?

I guess the answer is along the lines of "because it's much more complex than it looks", but honestly I have no idea.

edit: Some precisions regarding the answers and comments below.

The problem with this code is that each time this function is called, the stack grows "one integer too much". Of course this is no problem in the example, but consider large variables and recursive calls and you have a stack overflow that could be easily avoided.

What I suggest is a memory optimization, but I don't see how it would damage performance.

And by the way, this happens in release builds, will all optimizations on.

解决方案

Reusing stack space for locals like this is a very common optimization. In fact, on an optimized build, if you didn't take the address of the locals, the compiler might not even allocate stack space and the variable would only live in a register.

You might not see this optimization happen for several reasons.

First, if optimizations are off (like a debug build) the compiler won't do either of these to make debugging easier - you can view the value of A even if it is no longer used in the function.

If you are compiling with optimizations, my guess would be since you are taking the address of the local and passing it to another function, the compiler doesn't want to reuse the store since it is unclear what that function is doing with the address.

One can also imagine a compiler that would not use this optimization unless the stack space used by a function exceeds some threshold. I don't know of any compilers that do this, since reusing the space of local variables that are no longer used has zero cost and could be applied across the board.

If stack growth is a serious concern for your application, i.e., in some scenarios you are hitting stack overflows, you should not be relying on the compiler's optimization of stack space. You should consider moving large buffers on the stack to the heap and work to eliminate very deep recursion. For example, on Windows threads have a 1 MB stack by default. If you're concerned about overflowing that because you're allocating 1k of memory on each stack frame and going 1000 recursive calls deep, the fix is not to try to coax the compiler to save some space off of each stack frame.

这篇关于C ++堆栈和作用域的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆