2012-06-19 106 views
3
#include <iostream> 
#include <string> 
using namespace std; 

string 
crash() 
{ 

} 

int 
noCrash() 
{ 

} 

int 
main() 
{ 
    crash(); // crashes 
    // noCrash(); // doesn't crash 
    return 0; 
} 

功能崩潰(,崩潰,並MinGW的G ++ 4.6.2和功能noCrash()沒有問題執行。爲什麼函數返回字符串崩潰而沒有返回語句?函數返回的std :: string崩潰沒有return語句,不像它返回int的函數沒有return語句

+1

我很驚訝它編譯。 –

+0

你必須返回一些東西。 – 2012-06-19 07:13:02

+0

@PaulMitchell:程序在語法和語義上都是有效的......即使它確實會導致_undefined behavior_如果它實際運行。 –

回答

7

兩者都是未定義的行爲,即使noCrash也會崩潰。

4

可能是因爲當你調用crash編譯器試圖破壞這是從來沒有創建的臨時std::string對象。

由於這兩個函數都有未定義的行爲推測有些徒勞無益。

7

從標準6.6.3/2

而不表達式的return語句可用於僅在功能 不返回一個值,即,與返回類型的函數 空隙,一構造函數(12.1)或析構函數(12.4)。具有非空類型表達式的返回語句 只能在返回值的函數 中使用;表達式的值將返回給函數的調用者 。該表達式被隱式轉換爲它出現的函數的返回類型 。返回語句 可能涉及臨時對象的構建和複製(12.2)。 流失函數的末尾相當於沒有 值的返回;這會導致在返回值 函數中出現未定義的行爲。

5

很多這些都是未定義的,但它可以幫助理解這些觀察的實際原因 - 它可以幫助解決故障,甚至性能和空間設計。因此,在實際意義上,如果函數未能返回一個值,那麼基本上無法設置調用者期望該值的寄存器或存儲器;它似乎會返回曾經存在的垃圾。如果返回類型是int,那麼你只是給自己一個垃圾值,但對於字符串,你有一個垃圾值,它直接或間接地指向字符串使用的堆內存以存儲文本值,參考計數器或其他管理數據。稍後在程序中,調用代碼將嘗試通過刪除指針來釋放堆內存。用垃圾值刪除指針很可能會導致程序崩潰。