从可变参数函数的调用引发异常崩溃一例引发的一些思考

       使用va_list、va_start、va_arg和va_end这组宏实现的可变参函数,是在运行时动态从函数调用堆栈中依次解析出传入的各个可变参数的(解析出可变参数的栈内存地址,读出可变参数的值(读出可变参数内存中的内容))。

       以C调用约定为例,从汇编代码来看函数调用,在call函数前,依次将各个参数从右到左依次入栈,包括函数声明中的已经固定类型的参数和可变参数。从汇编代码来看一个完整的函数调用的栈分布,先将各个参数压入栈中,然后通过call指令转进被调函数中。

       call指令内部会做两个操作,一是将主调函数的下条指令作为返回地址压入到栈中,二是实现主调函数到被调函数的跳转。进入到被调函数中后,先将当前的ebp,即主调函数的函数栈基址压入栈中保存下来,以供栈回溯使用(通过ebp值找到函数调用的返回地址)。

        所以,C调用约定的函数在调用时,依次存入栈中的是:从右到左参数入栈 -> 主调函数的返回地址入栈-> 主调函数的ebp栈基址入栈。注意,此处讲的参数入栈,是将参数内容(内存中的内容)拷贝到栈内存中,如果传入的参数是int或者指针,则将int值和指针变量的值存放到栈内存中,如果是个类对象或者结构体对象,则是将对象的数据内容(对象内存中的内容)拷贝到栈上。被调函数可以从栈中直接访问传入的参数内容,源码中被调函数通过函数参数变量访问传入的参数值,其实在汇编代码上看,是访问函数调用时函数参数入栈时对应的栈内存中的内容。

       栈是从大地址向小地址使用的,对于参数从右到左顺序入栈的C调用,右边先入栈的参数(内

猜你喜欢

转载自blog.csdn.net/chenlycly/article/details/80694459