网站首页 > 技术教程 正文
F.43: Never (directly or indirectly) return a pointer or a reference to a local object
无论直接还是间接,永远不要返回指向局部对象的指针或引用。
Reason(原因)
To avoid the crashes and data corruption that can result from the use of such a dangling pointer.
为了避免使用这个悬空指针而引起崩溃和数据破坏。
Example, bad(反面示例)
After the return from a function its local objects no longer exist:
当程序从函数退出之后,函数中的局部变量就不再存在了。
int* f() { int fx = 9; return &fx; // BAD } void g(int* p) // looks innocent enough { int gx; cout << "*p == " << *p << '\n'; *p = 999; cout << "gx == " << gx << '\n'; } void h() { int* p = f(); int z = *p; // read from abandoned stack frame (bad) g(p); // pass pointer to abandoned stack frame to function (bad) }
Here on one popular implementation I got the output:
这是一段很一般代码,我得到了以下输出:
*p == 999 gx == 999
I expected that because the call of g() reuses the stack space abandoned by the call of f() so *p refers to the space now occupied by gx.
我预期如此是因为对g()的调用再次使用了调用f()之后放弃的堆栈空间,因此*p访问的是现在被gx占用的空间。
- Imagine what would happen if fx and gx were of different types.想象一下如果fx和gx是不同类型时会发生什么。译者注:变量会被修改为完全无关的值。
- Imagine what would happen if fx or gx was a type with an invariant.想象一下如果fx和gx是一种包含不变式的类型时会发生什么。译者注:不变式会被莫名其妙地破坏。
- Imagine what would happen if more that dangling pointer was passed around among a larger set of functions.进一步想象一下如果悬空指针在更多函数之间传递是会发生什么。译者注:会有跟多的函数和局部变量受到影响。
- Imagine what a cracker could do with that dangling pointer.想象一下破密者会如果处理悬空指针。译者注:破密者可以通过这个人变量改变函数的行为。
Fortunately, most (all?) modern compilers catch and warn against this simple case.
幸运的是,大部分(所有?)现代编译器都可以捕捉并对这个简单的情况报警。
Note(注意)
This applies to references as well:
这一问题也适用于引用的情况。
int& f() { int x = 7; // ... return x; // Bad: returns reference to object that is about to be destroyed }
Note(注意)
This applies only to non-static local variables. All static variables are (as their name indicates) statically allocated, so that pointers to them cannot dangle.
这个问题只适用于非静态全局变量。所有的静态变量(就像名称所表示的)都是静态分配内存,因此指向它们的指针不会悬空。
Example, bad(反面示例)
Not all examples of leaking a pointer to a local variable are that obvious:
不是所有泄漏指向局部变量指针的示例都是明显的。
int* glob; // global variables are bad in so many ways template<class T> void steal(T x) { glob = x(); // BAD } void f() { int i = 99; steal([&] { return &i; }); } int main() { f(); cout << *glob << '\n'; }
Here I managed to read the location abandoned by the call of f. The pointer stored in glob could be used much later and cause trouble in unpredictable ways.
这段代码中我设法读取函数f被调用后放弃的局部变量。保存在glob中的指针可以在很长时间之后被使用并以无法预期的方式带来麻烦。
Note(注意)
The address of a local variable can be "returned"/leaked by a return statement, by a T& out-parameter, as a member of a returned object, as an element of a returned array, and more.
局部变量的地址以多种方式被“返回”或者说被泄漏。具体的方式可以是通过返回语句,T&类型的输出参数,返回值对象的成员,返回值数组的元素或者是其它方式。
Note(注意)
Similar examples can be constructed "leaking" a pointer from an inner scope to an outer one; such examples are handled equivalently to leaks of pointers out of a function.
类似地,也可以构造出从内部作用域向外部作用域“泄漏”指针的例子。这样的例子等价于向函数外部泄漏(指向局部变量的)指针。
A slightly different variant of the problem is placing pointers in a container that outlives the objects pointed to.
这个问题的稍微不同的版本是将指针放到生命周期超过指针所指向对象的容器中的情况。
See also: Another way of getting dangling pointers is pointer invalidation. It can be detected/prevented with similar techniques.
参见:产生悬空指针的另一种情况是指针无效化。它可以通过类似的技术检查或防止。
译者注:指针无效化应该是指针本来指向的是一个有效对象,但后来对象被销毁而指针没有被同时清空的情况。
Enforcement(实施建议)
- Compilers tend to catch return of reference to locals and could in many cases catch return of pointers to locals.编译器倾向于捕捉返回指向局部变量的引用的情况,也可以在很多情况下捕捉返回指向局部变量的指针的情况。
- Static analysis can catch many common patterns of the use of pointers indicating positions (thus eliminating dangling pointers)静态分析可以发现许多使用指针表示位置的通常形式,这样就可以排除悬空指针。
觉得本文有帮助?请分享给更多人。
更多更新文章,欢迎关注微信公众号【面向对象思考】
面向对象设计,面向对象编程,面向对象思考!
猜你喜欢
- 2024-10-04 C++|虚函数多态机制的虚函数表及其指针的内存布局及手动引用
- 2024-10-04 C|指针分类与void指针的赋值、解引用与算术运算
- 2024-10-04 第5课,引用方式(锁定) 锁定引用值
- 2024-10-04 C++函数参数采用变量、引用和指针的区别
- 2024-10-04 Java String 手工引用指针 java中指针和引用
- 2024-10-04 C++核心准则C.145:通过指针或引用访问多态对象
- 2024-10-04 C\C++语言11|引用做为函数参数与返回值及与指针的区别
- 2024-10-04 Excel中的引用方式,看过之后你就懂
- 2024-10-04 C++,常量及sizeof函数,传值调用、指针调用和引用调用的区别
- 2024-10-04 C++ 继承中指针和引用类型特点 c++指针的引用传参数形式
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- sd分区 (65)
- raid5数据恢复 (81)
- 地址转换 (73)
- 手机存储卡根目录 (55)
- tcp端口 (74)
- project server (59)
- 双击ctrl (55)
- 鼠标 单击变双击 (67)
- debugview (59)
- 字符动画 (65)
- flushdns (57)
- ps复制快捷键 (57)
- 清除系统垃圾代码 (58)
- web服务器的架设 (67)
- 16进制转换 (69)
- xclient (55)
- ps源文件 (67)
- filezilla server (59)
- 句柄无效 (56)
- word页眉页脚设置 (59)
- ansys实例 (56)
- 6 1 3固件 (59)
- sqlserver2000挂起 (59)
- vm虚拟主机 (55)
- config (61)
本文暂时没有评论,来添加一个吧(●'◡'●)