(私にとっては) 奇妙なアクセス違反の例外が表示されます。できるだけ問題を減らすようにします。クラス A とシングルトン オブジェクト sing_ があります。コードは次のようになります。
class A {
A();
Sing& sing_;
}
A::A() : sing_(Sing::instance()){
call a method that creates a local copy of Singleton Sing.
....
}
Sing クラスは Singleton から継承します。
class Sing : public Singleton<Sing>{
friend class Singleton<Sing>;
....
}
シングルトン自体はそのように見えます(これはQuantLibライブラリでの実装です)
template <class T>
class Singleton : private boost::noncopyable {
public:
static T& instance();
protected:
Singleton() {}
};
template <class T>
T& Singleton<T>::instance() {
static std::map<Integer, boost::shared_ptr<T> > instances_;
#if defined(QL_ENABLE_SESSIONS)
Integer id = sessionId();
#else
Integer id = 0;
#endif
boost::shared_ptr<T>& instance = instances_[id];
if (!instance)
instance = boost::shared_ptr<T>(new T);
return *instance;
}
私のプロジェクト コードは Qt GUI 環境に埋め込まれています。デバッグモードで起動しても問題ありません。リリースモードで起動しようとすると、状況がひどく変わります。これが主な方法です。
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
GUI w;
w.show();
w.setup(argc, argv);
return a.exec();
}
最後に、クラス GUI は次のように省略されます。
class GUI : public QMainWindow
{
Q_OBJECT
public:
GUI(QWidget *parent = 0, Qt::WFlags flags = 0);
~GUI();
private:
boost::shared_ptr<A> a_;
};
このコードをリリース モードで開始すると、次のことが起こります。
___tmainCRTstartup() というメソッドが呼び出されます。そこで、メソッド _WinMain が呼び出されます。
このメソッドWinMain 内で (main メソッドが呼び出されて GUI オブジェクトが作成される前であっても)、A のコンストラクターが呼び出されます。これは、sing メンバーが初期化されることを意味します。
sing_ は Sing::instance() の呼び出し中に初期化されます。これまでのところ、すべて問題ないようです。
A のコンストラクターが実行されます。その中で、シングルトン オブジェクト Sing へのローカル参照が作成されます。Sing::instance() を呼び出すと、その行でアクセス違反が発生します
boost::shared_ptr<T>& instance = instances_[id];
その場所 (リリース モードでデバッグ) の instances_[id] を見ると、マップはかなり破壊されているように見えます。これは、マップに 1 つの要素があることを意味します。しかし、キーは 0 ではなく、非常に負の整数であり、値も奇妙に見えます。
ここで何がうまくいかないのか、私にはまったくわかりません。
A のメンバー sing_ を静的メンバーに変更すると、問題が修正されます。
class A {
A();
static Sing& sing_;
}
Sing& sing_ = Sing::instance();
A::A() {
call a method that creates a local copy of Singleton Sing.
....
}
それはもちろん素晴らしいことですが、これら 2 つの実装の「大きな」違いは何なのか、本当に疑問に思っています。最初の方法がアクセス違反で終わるのはなぜですか? どんなヒントでも大歓迎です。