C++中在函数内获取引用传参的地址使用是否存在风险?
问题分析
示例代码如下:
void func(Param& p1, Param& p2) { addObjectByPointer(&p1); addObjectByPointer(&p2); } int main() { Param p1; Param* p2 = new Param; func(p1, *p2); }
针对问题逐一说明:
对引用类型形参取地址能否正确获取原始变量的地址
完全可以,这是C++标准规定的确定行为。引用本质就是对象的别名,没有自身独立的内存地址,对引用做取地址操作,返回的必然是它绑定的原始对象的内存地址。
上面的代码里,func内取到的&p1就是main函数里栈上p1对象的地址,&p2就是main里new出来的堆上Param对象的地址,这一步操作本身没有语法问题。
上述代码写法是否存在风险
存在很典型的安全隐患,问题不出在取地址这一步,而出在裸指针传递没有任何生命周期和所有权约束:
- 第一个参数绑定的是栈上局部对象,生命周期完全由所在作用域决定,一旦离开作用域就会自动析构;
- 第二个参数绑定的是堆上手动申请的对象,代码里既没约定谁负责释放,很容易出现内存泄漏,也没法保证不会被提前释放,出现重复释放的问题。
沿调用链路传递的指针能否随时安全访问原对象
绝对不行。
指针的有效性完全和指向对象的存活状态绑定:只要原对象生命周期结束(栈对象出作用域、堆对象被delete),或者对象内存被移动、回收后重新分配,之前存下来的指针就会变成悬空指针,这时候访问指针属于未定义行为,轻则读到脏数据,重则直接导致程序崩溃。
不要觉得拿到了地址就能随时访问,C++不会帮你做对象生命周期的托管。要安全传递对象地址,要么严格限制指针的使用范围,确保所有通过指针的访问都发生在原对象的生命周期内;要么使用智能指针明确所有权,从语法机制上保证对象存活时指针才可用。
内容的提问来源于stack exchange,提问作者ram
相关产品推荐
相关产品推荐

