熟悉掌握c++中函数调用堆栈,内存管理,智能指针

c++如何在程序运行时为程序调用内核堆栈的呢?

CPU是如何识别被调参数的呢?怎么保存传递的参数的呢?

所以cpu引进了栈的数据结构来完成函数的调用,函数调用时依次把参数压栈,然后调用函数,

调用完以后从堆栈中取出数据并计算,计算结束后清栈

回想这个时先回想一下虚拟空间的空间布局和调用约定

int sumint aint b

{

  int tmp=0;

tmp=a+b;

return tmp;

}

int main()

{

  int a=10;

int b=20;

 int ret=0;

ret=sum(a,b);

Printf(“%d”,ret);

}

虚拟空间内存布局:1G内核空间,3G用户空间

保留区  128M 不可读不可写

0x00000000

--

0x0804 8000

.text 指令

 

.data

 

.bss未初始化

(执行前清0

heap

向下开辟 

共享库

 

stack 栈   

向上开辟 

环境变量

0xc000 0000

DMA

 

NORMAL

 

HIGHMEM

0xffff ffff

 

 

函数调用的具体情况:

Push 压栈,pop 出栈,eaxebx:存放数值

ebp:栈底指针寄存器esp:栈顶指针寄存器call:压入下一行的指令地址

返回值:4字节 eax带出,8 eax  edx  8 用临时量带回(在调用方栈帧开辟,临时量在形参压栈后压栈)

具体实现如下:

0x0000 0000             esp

tmp

main函数的栈底指针     ebp

下一条指令的地址 (&&printf

eax  10

eax  20

X X X X X X X X X X

ret   0

b    10

a    20

mainCRTstartup函数的栈底指针

 

 

关于四种调用约定:

参数的传递中有两个问题需要明确 约定符号的生成,形参的入栈顺序(pasclcall),形参的开辟和清理方式

_cdeclc标准调用约定      调用方开辟,调用方清除 如上

_stdcallwindows标准调用约定   自右向左入栈 调用方开辟,被调用方清除

_fastcall:快速调用约定   形参不开辟 在寄存器中存放 若形参个数过多的情况则

1)形参字节小于等于4  前两个形参不开辟内存寄存器带入被调用方 第三个开始和_stdcall调用约定相同

2)形参字节数大于4 和——stdcall相同,调用方开辟,被调用方清理

 

_thiscallc++成员方法的调用约定 ,对参数个数不定的 调用者清栈,否则函数自己清栈

//汇编太麻烦了,你们可以自己去看看

c++是如何管理内存的呢?

大家都知道c语言在管理内存时候的方式:即上图;其实c++的内存管理也是如此

那就说一下c++的几种存储结构吧(堆,栈,全局/静态存储区,文字常量区,text段)

栈:局部变量,参数,编译器自动开辟释放,相当于计算机系统的数据结构分配专门的寄存器来存储栈的地址,所以效率较高,内存空间连续,但由于向下开辟,空间有限

堆:手动开辟释放,向上开辟,内存空间无限制,内存不连续,会有内存碎片产生,具体的newmalloc以后会具体说明

全局/静态存储区:全局变量,静态变量,程序结束时自动释放,包括data段和bass

文字常量区:存放在data

text段:存放程序的二进制代码