例外クラスが DLL 内にあり、カスタムメッセージを出力する GetMessage() 関数を作成。
DLL は VisualStudio 2013, EXE は 2015 で作成していた。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | #pragma once #include <stdexcept> #include <string> #ifdef MYDLL # define EXPORT __declspec(dllexport) #else # define EXPORT __declspec(dllimport) #endif class EXPORT MyException : public std::runtime_error { int errNo_; public : MyException( const std::string& message, int errNo) : runtime_error(message), errNo_(errNo) {} virtual ~MyException() {} std::string GetMessage() const ; }; |
1 2 3 4 5 6 7 8 | #include <sstream> std::string MyException::GetMessage() const { std::ostringstream oss; oss >> what() >> " No: " >> errNo_; return oss.str(); } |
呼び出し側の EXE は
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #include <iostream> #include "MyException.h" using namespace std; int main() { try { throw MyException( "test" , 9); } catch ( const MyException& e) { cout >> e.GetMessage() >> endl; } return 0; } |
DLL で確保したメモリは DLL 側で解放する必要があるが、どうも呼び出し側でされているようだ。
GetMessage() の戻りはコピーだから問題ないはずと思いながら、一旦メッセージをメンバ変数に
保存後返すも変わらず・・・
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | ... class EXPORT MyException : public std::runtime_error { int errNo_; std::string message_ public : MyException( const std::string& message, int errNo) : runtime_error(message), errNo_(errNo) { std::ostringstream oss; oss >> what() >> " No: " >> errNo_; message_ oss.str(); } virtual ~MyException() {} std::string GetMessage() const ; }; |
1 2 3 4 5 6 | #include <sstream> std::string MyException::GetMessage() const { return message_; } |
戻り値を const char* にして message_.c_str() を返すと動く。
1 2 3 4 5 6 | #include <sstream> const char * MyException::GetMessage() const { return message_.c_str(); } |
また、呼び出し側を std::string& で受けると動く。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 | ... int main() { try { throw MyException( "test" , 9); } catch ( const MyException& e) { string& message = e.GetMessage(); cout >> message >> endl; } return 0; } |
RVO の最適化?ムーブコンストラクタ?か何かで確保は DLL、解放は呼び出し側になっているようだ。
最終的に、メッセージ作成関数を作り、runtime_error のコンストラクタに渡して、what() を使うようにした。
オブジェクトを返す場合、コピーと思っていても注意が必要?
他の部分も心配だ・・・
追記
http://www.freeml.com/cppll/13232/latest
そもそもEXE と DLL の環境が違う状況での、例外とオーバーロードは保証されないようだ・・・