2012-09-05 36 views
1

可能重複:
Can a local variable's memory be accessed outside its scope?C++返回參考函數範圍內聲明

我做一些代碼審查時看到的功能。

wchar_t* GetString(HINSTANCE hInstance, UINT SID) 
{ 
    wchar_t buf[2048] = {0}; 
    LoadStringW(hInstance, SID, buf, sizeof(buf)/sizeof(wchar_t)); 
    return &buf[0]; 
} 

void SomeWork() 
{ 
    std::wstring str(GetString(hInst, 123)); 
} 

我想BUF應該被銷燬後立即函數返回, 使指針& BUF [0]可能無效。 但它似乎工作正常,它是如何工作的? 這是一個很好的設計? 謝謝。

回答

5

我想BUF後應權函數返回被破壞,所以 指針&buf[0]可能無效。

你的思想是100%正確。

但似乎做工精細,它是如何工作的?

它「作品」,因爲持有buf陣列調用堆棧的一部分正好沒有被實際使用它時寫入了其內容。

但這不確定的行爲,以及不確定的行爲意味着什麼都可能發生,並且可以包括「召喚一個世界末日」和/或「的工作就好了。」這次你真幸運。

而且它是一個優良的設計?

不,這是一個可怕的設計。幸運的是它有一個簡單的修復方法:只需返回std::wstring本身。

std::wstring GetString(HINSTANCE hInstance, UINT SID) 
{ 
    wchar_t buf[2048] = {0}; 
    LoadStringW(hInstance, SID, buf, sizeof(buf)/sizeof(wchar_t)); 
    return std::wstring(buf); 
} 

void SomeWork() 
{ 
    std::wstring str = GetString(hInst, 123); 
} 

在這種情況下,所有非愚蠢的C++編譯器都會優化臨時對象,所以此代碼在實踐中沒有性能損失。實際上,即使關閉所有優化,Visual C++編譯器也會優化這種情況。

這種特殊的優化被稱爲return value optimization (RVO)。如果您的C++編譯器即使在設置爲最高優化級別時也不會執行RVO,請換另一個。

3

不是。這是嚴重的缺陷。返回指向本地對象的指針或引用是未定義的行爲。這意味着一切都可能發生,包括啓動WWIII。在你的情況下,未定義的行爲就像它一樣「工作正常」。僥倖。

1

從理論上講,這是不確定的行爲,這意味着什麼可能發生,有時包括工作(顯然)正確。然而,未定義意味着無法保證它始終有效。

它現在看起來工作的原因是因爲由GetString修改的內存沒有被您讀取它時執行的任何其他代碼修改。換句話說,你很幸運。

1

我以爲buf應該在函數返回後立即銷燬,所以指針& buf [0]可能無效。

這是正確的。 buf的使用期限已結束;它的內存可能會或可能不會被用於不同的對象;和任何訪問它給未定義的行爲。

但似乎做工精細,它是如何工作的?

因爲在很多平臺上,自動變量存儲在堆棧中,並且函數的堆棧內存在函數返回時不會變爲不可訪問。這意味着對變量的(無效懸掛引用)通常仍然會顯示爲舊值,直到調用另一個函數並重用該內存爲止。

而且它是一個優良的設計?

當然不是。您依賴未定義的行爲,並且您的代碼可能會停止出現,原因很多 - 更改平臺或編譯器,爲您的代碼添加另一個函數調用,或者改變月亮的移動階段。我會返回std::wstring