Download - 私とC++ in 例外安全day
![Page 1: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/1.jpg)
私とC++In 例外安全Day
![Page 2: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/2.jpg)
自己紹介
石川達也
株式会社Codeer代表取締役
C, C++, C#, Java
![Page 3: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/3.jpg)
Exceptional C++ 読書会で
常識のある人間です。
![Page 4: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/4.jpg)
Exceptional C++ 読書会で
常識のある人間です。
・gotoを使わない。
![Page 5: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/5.jpg)
Exceptional C++ 読書会で
常識のある人間です。
・gotoを使わない。・Duff ‘s deviceなどもっての外。
![Page 6: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/6.jpg)
Exceptional C++ 読書会で
常識のある人間です。
・gotoを使わない。・Duff ‘s deviceなどもっての外。・VC++をDisらない。
![Page 7: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/7.jpg)
今日は、体験談を語らせてもらいます。
参考にするもよし、マサカリ投げるもよし。(優しく)
![Page 8: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/8.jpg)
アジェンダ
・例外
・テンプレート活用例・関数ポインタキャスト・アロケータ記憶・AOPもどきログ
![Page 9: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/9.jpg)
例外
・リソース系
・プログラムミス系
![Page 10: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/10.jpg)
注)OutOfMemory場合によって・・・
リソース系or
プログラムミス系
例外
![Page 11: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/11.jpg)
・リソース系FileIO他の機器との通信
例外安全に作ります。最終的には、catchして適切に処理。て言うか、例外とは思っていない。
例外に関する姿勢
![Page 12: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/12.jpg)
・プログラムミス(ASSERT含む)
問題はこれ。
例外に関する姿勢
![Page 13: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/13.jpg)
std::vector<int> buf;・・・buf[index] = 100; //範囲外とか。
例外(プログラムミス)
![Page 14: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/14.jpg)
swtich(val) {・・・default://予期せぬ値とか。
ASSERT(FALSE);break;
}
例外(プログラムミス)
![Page 15: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/15.jpg)
可能な限りの終了処理をしてプロセスを停止させる。
注)お客様との調整が必須。
例外(プログラムミス)
![Page 16: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/16.jpg)
堅牢性と正当性は相反する。
例外(プログラムミス)
![Page 17: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/17.jpg)
size_t index = ・・・;std::vector<int> buf;・・・ASSERT_DEAD(index < buf.size());buf[index] = 100;
例外(プログラムミス)
![Page 18: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/18.jpg)
swtich(val) {・・・default:
ASSERT_DEAD(FALSE);}
例外(プログラムミス)
![Page 19: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/19.jpg)
例外(プログラムミス)
そのまま動作させると・・・
・永続データを壊すかも。
・原因特定困難な不具合になる。
・使われない復帰コードでコードが腐敗し、さらなる不具合を招く。
![Page 20: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/20.jpg)
例外(プログラムミス)
潔く終了すると・・・。
・変なデータができない。
・不具合解析が楽。
・コードはスッキリ。↓
結果的にリリース品質が劇的にUP。
![Page 21: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/21.jpg)
例外(プログラムミス)
あ、
「この辺は無理に終了しなくても・・・」とかは無し。
その切り分けは難しく、だんだん、生き恥をさらす方向に行くので。
![Page 22: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/22.jpg)
次
![Page 23: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/23.jpg)
テンプレート活用例
①関数ポインタキャスト
![Page 24: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/24.jpg)
FARPROC GetProcAddress(
HMODULE hModule, LPCSTR lpProcName);
おなじみ、DLL関数取得。
①関数ポインタキャスト
![Page 25: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/25.jpg)
関数のロードが面倒・・・。
typedef void (__stdcall *FuncType)(int value);FuncType Func = NULL;
Func = (Func)GetProcAddress(h, “Func”);
①関数ポインタキャスト
![Page 26: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/26.jpg)
ちょっとしたユーティリティーを作っておく。
template<typename T>void GetEx(HMODULE hModule, LPCSTR name,
T& func) {
func = (T)GetProcAddress(h, name);}
#define GETPROC(h, f) GetEx(h, #f, f)
①関数ポインタキャスト
![Page 27: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/27.jpg)
スッキリ!
void (__stdcall *Func)(int value);
GETPROC(h, Func);
①関数ポインタキャスト
![Page 28: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/28.jpg)
①関数ポインタキャスト
ついこないだも、使っちゃいました。
→コードへ。http://www.codeer.co.jp/technical-notes/NativeAndNet
![Page 29: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/29.jpg)
②アロケータ記憶
DLLで、ランタイム異なることありますよね・・・?
(゚◇゚)共通にすれば済む話・・・。
![Page 30: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/30.jpg)
Exe dll
メモリ管理メモリ管理
そうすると、ヒープも違うんですよね。
②アロケータ記憶
混ぜるな危険
![Page 31: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/31.jpg)
②アロケータ記憶
でも、動的なコンテナ使いたいんです。
![Page 32: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/32.jpg)
②アロケータ記憶
で、コンテナ作りました。
Σ⊂( ̄□ ̄~j
![Page 33: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/33.jpg)
template<typename T>
class ArrayAllocator
{
public:
T* (__stdcall *New)(unsigned int size);
void (__stdcall *Delete)(T* ptr);
ArrayAllocator() : New(NewCore),Delete(DeleteCore){}
②アロケータ記憶
![Page 34: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/34.jpg)
private:
static T* __stdcall NewCore(unsigned int size)
{
return new T[size];
}
static void __stdcall DeleteCore(T* ptr)
{
if (ptr)
{
delete[] ptr;
}
}};
![Page 35: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/35.jpg)
//配列template<typename T>
class Array
{
ArrayAllocator<T> _heap;
・・・};
//文字列class WString
{
Array<WCHAR> _core;
・・・};
![Page 36: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/36.jpg)
struct Data
{
Array<int> ar;
WString str;
};
void _stdcall Func(Array<Data>& a)
{
//データを詰める}
入れ子もOK!
![Page 37: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/37.jpg)
{Array<Data> a;Func(a);
}抜けたら、それぞれのメモリ管理のdeleteが呼ばれる。
Void Func(Array<Data>& a){
a.resize(100);a[99].ar.resize(100);a[99].str = L“abc”;
②アロケータ記憶
![Page 38: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/38.jpg)
③AOPもどきでログを仕込む
関数の呼び出し順をログ出力したことありますよね?
![Page 39: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/39.jpg)
③AOPもどきでログを仕込む
全部に、いちいち仕込むのは面倒!
横断的(AOP)に処理したい!
![Page 40: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/40.jpg)
template <typename Ret, int fileNo, int lineNo>
struct AOPLog {
//DLL関数の型typedef Ret (__stdcall *FuncType)();
//ログstatic std::string& Log()
{ static std::string log; return log; }
//DLL関数static FuncType& Func()
{ static FuncType func; return func; }
//ログ出力と呼び出しstatic Ret __stdcall Invoke()
{ Print(Log()); return Func(); }
};
![Page 41: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/41.jpg)
//戻り値voidで特殊化template <int fileNo, int lineNo>
struct AOPLog<void, fileNo, lineNo> {
typedef void(__stdcall *FuncType)();
static std::string& Log()
{ static std::string log; return log; }
static FuncType& Func()
{ static FuncType func; return func; }
static void __stdcall Invoke()
{ Print(Log()); Func(); }
};
![Page 42: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/42.jpg)
//ログ入り関数ロードtemplate<int fileNo, int lineNo, typename Ret>
void MakeLog(HMODULE h,
Ret (__stdcall *&func)(), LPCSTR name)
{
typedef AOPLog<Ret, fileNo, lineNo> T;
if (s_logMode) {
T::Func() =
(T::FuncType)::GetProcAddress(h,name);
T::Log() = funcName;
func = T::Invoke;
} else {
func = (T::FuncType)::GetProcAddress(h,name);
}
}
![Page 43: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/43.jpg)
//今のを引数が必要分繰り返す。//BOOST_PPとか。
//でヘルパマクロ#define LOG_GETEX(fileNo, h, f) \
MakeLog<fileNo, __LINE__>(h, f, #f)
//使うところは、すっきり。void (__stdcall *Func)();
LOG_GETEX(0, h, Func);
![Page 44: 私とC++ in 例外安全day](https://reader034.vdocuments.mx/reader034/viewer/2022042522/55aefc6c1a28abb7668b46dd/html5/thumbnails/44.jpg)
そろそろ時間!
ご清聴ありがとうございました。