【C++内存管理】浅析C++中函数调用时的内存分配-函数调用过程中其他函数相关的内存分布

#include
using namespace std;
void print()
{
	cout<<"hello world"<

以上代码,运行结果为:

[Hyman@Hyman-PC cplus]$ g++ array.cpp 
[Hyman@Hyman-PC cplus]$ ./a.out 
hello world

问题:为什么上述代码中根本没有调用print函数的语句,但是却打印出来了hello world的?


     在上一篇文章《浅析C++中函数调用时的内存分配-函数局部变量的内存分配》 中,最后留下了一个很有意思的问题,在代码中没有任何一个语句调用了 print() 函数,结果 print() 函数却被执行了。现在就对该问题进行分析:

  首先,我们先说明下C++中内存结构的分布,如下图所示:



【C++内存管理】浅析C++中函数调用时的内存分配-函数调用过程中其他函数相关的内存分布_第1张图片

    整个内存从低地址到高地址一次分为代码段、数据区、堆区、栈区、和命令行参数、系统变量存储区。

    代码段负责存放程序的各种指令,数据区主要存放全局数据、静态数据,而堆区是进行内存分配的地方,栈区是在进行局部变量存放的地方(栈顶是动态变化的),最上面的是存放系统变量和命令行参数等等。

    我们再看一下在执行一个函数时,函数怎么在栈区分配地址:

【C++内存管理】浅析C++中函数调用时的内存分配-函数调用过程中其他函数相关的内存分布_第2张图片

    在函数执行过程中,首先在栈中放入函数调用前的各个寄存器的执行状态,因为函数结束时需要将函数寄存器的值回到原位,然后存入形参(这点还有争议,和我之前看过的资料不一样,资料上说形参应该存到局部变量前面,但是我通过做实验并查看相关汇编代码,实际形参的存储位置应该如图),然后存入函数的返回地址(所谓返回地址就是函数结束后的下一条语句地址),然后是函数返回值(为返回值预留空间),最后是函数的局部变量。

    在这个例子中,我们定义了一个只含有一个元素的整形数组arr[1],然后数组越界把arr[2]存放了函数print的地址。

    先看此时的内存分布(只看局部变量部分):

【C++内存管理】浅析C++中函数调用时的内存分配-函数调用过程中其他函数相关的内存分布_第3张图片

     从图中可以看到,我们将print的函数地址放入了本该是函数返回地址的地方,这就导致test函数一结束就调用了print函数,也就打印出了”hello world”,这也就是在我们看来为什么没有调用函数print函数的语句,print函数却被调用的原因了。




你可能感兴趣的:(C++,c++,内存)