您好,登錄后才能下訂單哦!
這篇文章主要講解了“C++中為什么不要返回指向局部對象的指針或引用”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“C++中為什么不要返回指向局部對象的指針或引用”吧!
無論直接還是間接,永遠不要返回指向局部對象的指針或引用。
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 == 999gx == 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}
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)
靜態分析可以發現許多使用指針表示位置的通常形式,這樣就可以排除懸空指針。
感謝各位的閱讀,以上就是“C++中為什么不要返回指向局部對象的指針或引用”的內容了,經過本文的學習后,相信大家對C++中為什么不要返回指向局部對象的指針或引用這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。