【C++内存管理】浅析C++中函数调用时的内存分配-函数调用过程中其他函数相关的内存分布
来源:互联网 发布:linux deamon 编辑:程序博客网 时间:2024/04/29 06:24
#include<iostream>using namespace std;void print(){cout<<"hello world"<<endl;} void test(){int arr[1];arr[2]=(int)print;} int main(){test();return 0;}
以上代码,运行结果为:
[Hyman@Hyman-PC cplus]$ g++ array.cpp [Hyman@Hyman-PC cplus]$ ./a.out hello world
问题:为什么上述代码中根本没有调用print函数的语句,但是却打印出来了hello world的?
在上一篇文章《浅析C++中函数调用时的内存分配-函数局部变量的内存分配》中,最后留下了一个很有意思的问题,在代码中没有任何一个语句调用了print()函数,结果print()函数却被执行了。现在就对该问题进行分析:
首先,我们先说明下C++中内存结构的分布,如下图所示:
整个内存从低地址到高地址一次分为代码段、数据区、堆区、栈区、和命令行参数、系统变量存储区。
代码段负责存放程序的各种指令,数据区主要存放全局数据、静态数据,而堆区是进行内存分配的地方,栈区是在进行局部变量存放的地方(栈顶是动态变化的),最上面的是存放系统变量和命令行参数等等。
我们再看一下在执行一个函数时,函数怎么在栈区分配地址:
在函数执行过程中,首先在栈中放入函数调用前的各个寄存器的执行状态,因为函数结束时需要将函数寄存器的值回到原位,然后存入形参(这点还有争议,和我之前看过的资料不一样,资料上说形参应该存到局部变量前面,但是我通过做实验并查看相关汇编代码,实际形参的存储位置应该如图),然后存入函数的返回地址(所谓返回地址就是函数结束后的下一条语句地址),然后是函数返回值(为返回值预留空间),最后是函数的局部变量。
在这个例子中,我们定义了一个只含有一个元素的整形数组arr[1],然后数组越界把arr[2]存放了函数print的地址。
先看此时的内存分布(只看局部变量部分):
从图中可以看到,我们将print的函数地址放入了本该是函数返回地址的地方,这就导致test函数一结束就调用了print函数,也就打印出了”hello world”,这也就是在我们看来为什么没有调用函数print函数的语句,print函数却被调用的原因了。
0 0
- 【C++内存管理】浅析C++中函数调用时的内存分配-函数调用过程中其他函数相关的内存分布
- 【C++内存管理】浅析C++中函数调用时的内存分配-函数局部变量的内存分配
- x86系统C语言函数调用时的内存分布
- C语言中分配内存的函数
- C中程序的内存分配和函数调用时栈帧的创建
- C函数调用时的内存布局
- c程序中内存管理和内存分配函数[干货!!!]
- 在函数调用/子函数中进行动态内存的分配
- c的内存分配函数
- C++中函数调用中的内存分配
- C++中函数调用中的内存分配
- 从内存角度看C函数的调用过程
- 函数调用和栈的内存分配过程分析
- 主调函数分配内存的两次调用
- C语言中标准内存分配函数
- C内存管理相关函数
- nginx中内存对齐调用的函数
- c中内存函数
- EHCache的学习
- 装饰者模式
- QT的信号与槽原理(经典)
- 阿里移动推送Appcan-Android插件
- HDU 2191 珍惜现在,感恩生活 多重背包 .
- 【C++内存管理】浅析C++中函数调用时的内存分配-函数调用过程中其他函数相关的内存分布
- php获取当月天数及当月第一天及最后一天、上月第一天及最后一天实现方法
- Android 本次Toast取消上次的Toast的思路
- linux使用boost的进程库爆出5EiPKc]+0x23):对‘boost::system::system_category()’未定义的引用 collect2: error: ld return
- nginx 配置 Wosign 申请的免费的 SSL 证书
- 51nod-1287 加农炮
- 前端面经
- UVA1602
- 计算二进制中1的个数