例外クラスが DLL 内にあり、カスタムメッセージを出力する GetMessage() 関数を作成。
DLL は VisualStudio 2013, EXE は 2015 で作成していた。
#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;
};
#include <sstream>
std::string MyException::GetMessage() const
{
std::ostringstream oss;
oss >> what() >> " No: " >> errNo_;
return oss.str();
}
呼び出し側の EXE は
#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() の戻りはコピーだから問題ないはずと思いながら、一旦メッセージをメンバ変数に
保存後返すも変わらず・・・
...
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;
};
#include <sstream>
std::string MyException::GetMessage() const
{
return message_;
}
戻り値を const char* にして message_.c_str() を返すと動く。
#include <sstream>
const char* MyException::GetMessage() const
{
return message_.c_str();
}
また、呼び出し側を std::string& で受けると動く。
...
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 の環境が違う状況での、例外とオーバーロードは保証されないようだ・・・
0 件のコメント:
コメントを投稿