VS2010でSqPlusを実行したところ、スタックオーバーフローが!

squirrelスクリプト最近 バージョン3.0のベータ2版が出ましたね。とりあえず正式リリース版が出るまでは手を出さないつもりです。

最近Visual Studio 2005 から Visual Studio 2010にしてから事件が起きた・・・

今話していたsquirrelの扱いやすくしてくれるライブラリSqPlusなのだけども、Visual Studio 2010 でコンパイルし直したところ、スタックオーバーフローのエラーが突然現れた。
↑こんなかんじのやつね

とりあえず原因はわかった。下記のソースコードで説明します。

 class CTest
{
public:
	CTest(){m_i=0;}
	template <typename _ty&>
	CTest(_ty &val)
	{
		Set(val);
	}
	template <typename _ty&>
	CTest Set(_ty &val)
	{
		return *this;
	}
public:
	int m_i;
};

CTest TestGet()
{
	CTest ret;
	return ret;
}
int _tmain(int argc, _TCHAR* argv[])
{
	CTest obj;
	obj = TestGet();

	return 0;
}
こいつをVS2005で動かすと何事もなく動く!
だが、VS2010で動かすと22行目に注目してほしい、ここで戻るときに通常ならただ単にコピーされて終わりだが・・・
なぜか、06行目のコンストラクタが呼ばれ、メンバ関数のSetが呼び出され、そして13行目が呼び出され、無限ループとなりスタックオーバーフローとなります。

これは、19行目の戻るときに、

  戻り値 = CTest(ret) ←06行目呼び出し!

というかたちに変換されている
11行目も、

  戻り値 = CTest(*this) ←06行目呼び出し!

で、ちょっと調べてみるとVS2010はC++0xという仕様がはいったんですね^^; 本当に自分は勉強不足ですね・・・
ウィキペディアあたりで軽くC++0x を調べたところ、変換コンストラクタ状態になっていて、explicit 指定子を06行目に追加することにより上記の予期せぬ動きを制御することができるとのこと。
 class CTest
{
public:
	CTest(){m_i=0;}
	template <typename _ty&>
	explicit CTest(_ty &val)
	{
		Set(val);
	}
	template <typename _ty&>
	CTest Set(_ty &val)
	{
		return *this;
	}
public:
	int m_i;
};

CTest TestGet()
{
	CTest ret;
	return ret;
}
int _tmain(int argc, _TCHAR* argv[])
{
	CTest obj;
	obj = TestGet();

	return 0;
}
これにより無限ループはなくなり、SqPlusも普通に使えますね。

SqPlusより SquirrelObject.h
 
#ifndef _SQUIRREL_OBJECT_H_
#define _SQUIRREL_OBJECT_H_

class SquirrelObject
{
	friend class SquirrelVM;
public:
	SquirrelObject();
	virtual ~SquirrelObject();
	SquirrelObject(const SquirrelObject & o);
	SquirrelObject(HSQOBJECT o);
  template <typename _ty&>
  SquirrelObject(const _ty & val) { sq_resetobject(&_o); Set((_ty &)val); } // Cast away const to avoid compiler SqPlus::Push() match issue.
  template <typename _ty&>
  explicit SquirrelObject(_ty & val) { sq_resetobject(&_o); Set(val); }
  template <typename _ty&>
  SquirrelObject(_ty * val) { sq_resetobject(&_o); SetByValue(val); } // Set() would also be OK here. SetByValue() to save potential compiler overhead.

15行目にexplicit追加修正して実行してみたところ、スタックオーバーフローのエラーは消えました。普通に動きました。よかった、よかった

コメント 

コメントを残す