しらたまのコミッタ日記

2007-04-12

[]「変数エイリアス作成」で不正なポインタ処理 21:37

Ver.1.4015aの頃から発生していたバグの模様。

その頃のソースの差分とかを見てもよくわからなかったので、デバッガでちまちま追いかけてみました。

すると、どうもスタックに積んだ参照渡しした引数を消すときに、消しすぎている気配が濃厚です。

例えば以下のコード

Aとは整数

Bとは整数

AをBに変数エイリアス作成

スタックに積まれた状態だと、Stack[0]->AとStack[1]->B*1となるのですが、命令実行後、つまりスタックを消す直前にはB->Aとなっているので、Stack[0]->AとStack[1]->B->Aとなるわけです。

そして解放処理、hi_var_free関数変数解放するのですが、この中でリンク型はhi_getLink関数でもって参照先を確認し、参照カウントを減らします。ここで参照カウンタが負数になれば参照先を解放します。

で、hi_getLink関数なんですが、この関数リンク型が指す変数リンクだった場合は、そのリンクに対してhi_getLink関数を実行します。

つまりhi_getLink関数再帰的に呼び出されます。

これにより、hi_getLink関数一回の呼び出しで確実に値を取得できるのですが、単純にひとつ先だけ取得したいだけの時は困ります。

今回のケースが困るときです。

Stack[1]->B->Aにおいて、Stack[1]を解放しようとすると、hi_getLink関数に従ってAが取得され、参照カウンタが減らされます。

この結果、B->Aと参照があるにもかかわらず、Aは参照カウンタが実際の参照の数を下回ってしまいます。

このため、終了時に変数解放するとき、Aを解放しようとすると、本来は参照カウンタが1以上で、参照カウンタが減らされるだけのはずなのに、Aが解放されてしまうため、Bを解放しようとするときに、その(すでに解放されている)参照先も解放しようとしてエラーが出ます。

たまにエラーが出ないときがあるのは、解放された領域が不定なためです。

 

で、解決案なのですが、これがいい方法を思いつけません。

スタック変数を消すときだけ、hi_getLink関数を使わないようにすればいいのでしょうが、スタックは汎用のTHiArrayクラスで処理しているので、解放処理をいじるとこれを使っている処理全部に影響が出てしまいます。

プロパティにforStackとか増やせばいいのかもしれませんが、なんか不格好なような気も……

まあ他に方法が思いつかなければ、これで行かなければしょうがないんですが。

*1:->はリンク(エイリアス)を表します

FrankieFrankie 2012/06/28 02:00 More posts of this quaitly. Not the usual c***, please

rtpessgetrtpessget 2012/06/28 13:40 WZNNO9 <a href="http://tqbiobbimnpy.com/">tqbiobbimnpy</a>

larxcdqjpaelarxcdqjpae 2012/06/29 14:53 d72C9p , [url=http://ymcluirlkumx.com/]ymcluirlkumx[/url], [link=http://xniccmqghycj.com/]xniccmqghycj[/link], http://dmitljqlhnvi.com/

xwdriczkxwdriczk 2012/07/01 00:33 rrXxdX <a href="http://rlhstuzhogsx.com/">rlhstuzhogsx</a>

awezgwawezgw 2012/07/01 05:29 CtrnXh , [url=http://hapgyydkbbgv.com/]hapgyydkbbgv[/url], [link=http://oqgssvftuusp.com/]oqgssvftuusp[/link], http://owpqqjissnxd.com/

ゲスト



トラックバック - http://nadesiko.g.hatena.ne.jp/white-ball/20070412
200612
200701020304050708101112
20080103040506070912
200904
20100204
201104