总结

到目前为止我们已经掌握了函数调用的所有细节,现在我们需要利用这些知识来解答一些与函数相关的问题。

为什么尽量用循环来代替递归调用?

每一次函数调用都需要初始化和销毁栈帧,因此会带来额外的开销。同时当递归次数过多时,会导致栈内存耗尽,最终出现栈溢出。

为什么内联(inline)函数效率高?

内联函数跟普通的函数不一样,但是对于开发者而言你几乎可以使用和普通函数一样的方式去对待内联函数。在编译器实际编译出的指令中,只是把内联函数的指令copy到调用者的函数中,因此也就不会为它初始化栈帧。这样避免了栈帧所带来的开销,使用内联函数可以提升执行效率。

为什么静态变量在函数返回后不会被释放?

这是因为静态变量根本不在堆栈这块内存区域中,它存放在一个叫做静态区的地方,所以函数返回时销毁的是栈内存,并不会影响静态区。

什么是栈溢出攻击?

在上一节有讲到手动修改函数的返回地址,试想一下如果这个地址被攻击者修改成他自己指令的地址会导致什么后果?此时在函数返回时就会成功转而去执行攻击者的代码。这是一种很古老的攻击方式,现在已经有很多保护方式,例如stack canary、栈数据不可执行、随机化内存空间布局。

C/C++数组越界访问的危害?

C/C++并不会不检查数组越界访问,这将导致你越界访问的那段内存可能存放着相邻的其他变量,甚至是函数返回地址等重要数据。如果你还对其进行了修改,后果也很难想象,通常数组越界的bug也很难调试。

results matching ""

    No results matching ""