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()エラーコードのテキストの意味を表示したいのFormatMessage()ですが、まだ書いていないため、メソッドの実装は今のところ不完全です。

Visual Studio でこのコードを試していましたが、期待どおりに動作する代わりに、what()メソッドがガベージを返します。問題の解明にかなりの時間を費やし、さまざまなことを試した後、別のコンパイラを試すことになりました。

MinGW (GCC) を使用すると、コードは期待どおりにコンパイルおよび実行され、メッセージは思ったとおりに表示されます (誰かが興味を持っているconnect()場合は、インターネットに接続していないときに実行しようとしています)。

私はちょうど 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();
}
4

2 に答える 2

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これにより、オブジェクトの終了後にポインターが逆参照されない場合の動作が定義されました。

于 2013-02-10T21:41:53.413 に答える