2013-02-10 85 views
1

我最近在做一些套接字編程,並開始用C++編寫代碼。由於我試圖編寫的程序將有幾個組件必須通過套接字進行通信,因此我決定在一個類中封裝套接字通信。自定義的異常顯示一個可變的消息,在不同的編譯器中的行爲不同

由於有幾個錯誤可能發生,我決定創建一個套接字異常的一類,我定義它是這樣的:

class SocketException: public std::exception { 
public: 
    SocketException(const std::string &message); 
    ~SocketException() throw(); 
    virtual const char * what() const throw(); 
private: 
    std::string msg; 
}; 

實現如下:

SocketException::SocketException(const std::string &message) : msg(message) {} 
SocketException::~SocketException() throw() {} 

const char * SocketException::what() const throw() { 
    std::stringstream stream; 
    stream << msg + " Error number: "; 
    stream << WSAGetLastError(); 
    return stream.str().c_str(); 
} 

實施what()方法現在是不完整的,因爲我想通過​​顯示錯誤代碼的文本含義,但我還沒有寫過。

我在Visual Studio中試過這段代碼,但沒有像我期望的那樣工作,所以what()方法返回垃圾。花了相當一段時間試圖找出問題並嘗試不同的事情後,我最終嘗試了一種不同的編譯器。

使用MinGW(GCC)代碼編譯和按預期運行,消息顯示爲我認爲他們會(如果任何人有興趣,我只是試圖執行connect()時,未連接到Internet)。

我剛剛學習C++,我想知道問題出在哪裏,或者什麼是適當的方法。

編輯:感謝您的評論和回答,起初我認爲會是這樣,所以我用new分配流(即使知道它會泄漏,只是嘗試,因爲我明白new使用堆),結果是一樣的,這就是我:

const char * SocketException::what() const throw() { 
    std::stringstream *stream = new std::stringstream(); 
    *stream << msg + " Error: "; 
    *stream << WSAGetLastError(); 
    return (*stream).str().c_str(); 
} 
+2

要調用UB時,*流*對象將在方法返回一個這樣的char *通過c_str返回(破壞)是一個懸擺指針。你需要在類中使用char []來保持指針有效。 – 2013-02-10 21:41:22

+0

感謝您的評論,我認爲這是它,但在堆中分配的流產生了相同的結果。難道是'str()'調用會創建一個在某個時刻被銷燬的臨時對象? – 2013-02-10 21:57:40

+0

關於編輯,是的,'stringstream :: str()'返回一個底層字符串的副本,這是這個上下文中的臨時字符串。 – juanchopanza 2013-02-10 22:02:40

回答

1

你是返回一個指向一個變量是本地的what功能,因此可以使主叫方與懸擺指針:

const char * SocketException::what() const throw() { 
    std::stringstream stream; // this stringstream will die on exiting this scope 
    stream << msg + " Error number: "; 
    stream << WSAGetLastError(); 
    return stream.str().c_str(); 
} 

那就是未定義的行爲。這意味着什麼都可能發生。

的方法安全地返回const char*將是這樣的一個例子(顯然它不具有原始的預期功能性,它只是爲了說明的目的):

const char * SocketException::what() const throw() 
{ 
    return msg.c_str(); // msg lives as long as this SocketException instance 
} 

這已定義的行爲所提供的在SocketException對象死亡後指針不被解除引用。

+0

起初我也想到了,所以我嘗試使用'new'來分配流(即使知道它最終會泄漏),結果也是一樣的。我明白新會在堆中分配內存?我將編輯問題以表明這一點。感謝您的答覆。 – 2013-02-10 21:53:24

+0

@ A.Row你不想返回一個指向動態分配對象的指針。你可以做的是返回一個指向數據成員的指針。 – juanchopanza 2013-02-10 21:56:05

+0

謝謝,我想我會直接在類的構造函數中創建自定義消息,並在顯示時返回消息。 – 2013-02-10 22:04:39

0

如何
throw std::runtime_error("My very own message");

相關問題