问题描述
C++代码如下(基于Windows7系统使用VS2015进行编译):#include <iostream>
using namespace std;
void func1()
{
int a;
int b;
cout << "&a=" << &a << endl
<< "&b=" << &b << endl << endl;
}
int main()
{
func1();
func1();
func1();
func1();
func1();
return 0;
}
运行结果如下所示:
&a=002AFB48
&b=002AFB44
&a=002AFB44
&b=002AFB48
&a=002AFB44
&b=002AFB48
&a=002AFB44
&b=002AFB48
&a=002AFB44
&b=002AFB48所奇怪的是为什么第一次调用func1() 函数时,变量a在高地址、变量b在低地址,而后面四次调用 func1() 函数时,变量a在低地址、变量b在高地址,这是为什么呢?
主要原因R大都回答了,在O2下所有对func1的调用都inline了,a和b都变成了main函数的栈局部变量,这样5次对func1函数的inline会产生10个int的变量。变量个数增加了不少,但是里面大部分的life time不重叠,VC++里面有stack pack专门来把这些life time不重叠的,大小兼容的变量分配到同一个stack slot。下面是具体做法。
下面是被inline后的a和b按定义和使用的时间排序。
{
_b$1
_a$1
}
{
_b$2
_a$2
}
...第一对大括号是第一次inline, a和b都是live的而不能共享,分配两个stack slots。从第二对大括号开始,第一次inline的两个stack slot已经空闲可以重用。但是要重用也得挨个检查前面的stack slot看看是否兼容。那么答案来了,现在算法是倒序搜索的,差不多就是下面的代码, 所以_b$2重用了_a$1,_a$2只能重用_b$1,类推下去。作为验证可以在被inline的函数里面定义更多的变量,看看第二次及以后的调用的变量地址是不是刚好倒过来。
for (i = allocatedStackSlots - 1; i >= 0; i--)