BREWでsingleton(6)
とりあえずエミュレータ上では普通に動くので、ARMでコンパイルしてみたけど、エラーばっかり(;´Д`)
まず、間違ってたところがあるので修正。
const char* g_pModule = "self";
出来るわけ無いじゃん(;´Д`)
const char g_pModule[4] = { 0 };
修正修正っと。
これでコンパイルが出来たので、実機へ転送→実行してみました。
……落ちましたorz
( ・ω・)ナンデ?
まず一番怪しいのが自己書き換えの部分。えんらさんが実際に使っている(と思う)ので、あまり無いとは思うのだが、自分が何かポカしている可能性はある。
で、いろいろとやってみたけど、無事書き換えられていることを確認。
次に怪しいのが、IModuleとISingletonModuleを多重継承している部分。
BREWの仮想テーブルってかなり怪しいので、多重継承によって、仮想テーブルの位置がおかしくなって、実行時にアクセス違反になっているのでは無いだろうか。
なので、IModuleの実装を、ISingletonModuleの実装クラスから切り離して実装して、ISingletonModuleの実装クラスを、IModuleの実装クラスのメンバとして置いてみました。
class CSingletonModule : public ISingletonModule{ public: CSingletonModule() : stackPointer(0) { setSingletonModule(this); } void add(singleton_functor_interface* pFunctor){ _pFunctor[stackPointer++] = pFunctor; } //IModule::Releaseで、参照カウントが0になったら呼び出す void free(){ for(int i=stackPointer-1;i>=0;i--){ //functor実行 (*_pFunctor[i])(); } for(i=stackPointer-1;i>=0;i--){ delete _pFunctor[i]; } stackPointer = 0; } private: singleton_functor_interface* _pFunctor[10]; int stackPointer; }; class CModule : public IModule{ private: CSingletonModule singletonModule; void free(){ singletonModule.free(); } //以下はIModuleの継承したメンバを書いていく };
これでIModuleのせいで仮想テーブルがおかしくなることはない。
で、実機に入れて実行してみると、
……落ちましたorz
人生の厳しさを知りました(;つД`)
それでもめげずにいろいろとやって、遂に原因を突き止めました。
どうやら、
class IHoge{ public: virtual ~IHoge(){} virtual void foo()=0; }; const char g_pHoge[4] = { 0 }; IHoge* getHoge(){ return *(IHoge**)g_pHoge; } void setHoge(IHoge* hoge){ *(IHoge**)g_pHoge = hoge; } class CHoge : public IHoge{ public: CHoge(){ setHoge(this); } void foo(){ DBGPRINTF("hogehoge"); } };
というコードを書いたとき、
IHoge* hoge = new CHoge(); getHoge()->foo();
……これで落ちます(;´Д`)
→落ちませんでした。記述ミスが原因でした。ただ、ISingletonModuleを継承して使うと落ちますが(;´Д`)
多分、キャストをするときにポインタがずれるのが原因だと思いますが、細かいことは全然分かりません(;´Д`)
もちろん(constを外せば)エミュレータ上では動作します。
今回の場合だと、singletonの、getSingletonModuleの取得の所で落ちます。
解決方法は、継承を使わないようにすること。それで動きます。
でも根本的な解決になってないです(;´Д`)
BREWなんて嫌いだヽ(`Д´)ノウワァン