Entry No.
117
|
コンパイラ
ユニットの initialization セクションが実行される前に、そのユニット内の関数や手続きを呼び出すことが出来る
|
1.02 |
2.01 |
3.0 |
3.01 |
3.02 |
4.0 |
4.01 |
4.02 |
4.03 |
5.0 |
5.01 |
6.0 |
6.01 |
6.02 |
Kylix 1.0 |
Gotcha |
Gotcha |
Gotcha |
Gotcha |
Gotcha |
Gotcha |
Gotcha |
Gotcha |
Gotcha |
Gotcha |
Gotcha |
Gotcha |
Gotcha |
Gotcha |
Unknown |
|
|
解説
|
|
Reported by Scott Stephenson; checked by Arjen Broeze
initialization セクション内に呼び出し元がある場合、別のユニットの関数や手続きを、その別のユニットの initialization セクションが実行される前に呼び出すことが出来てしまいます。これは特徴であってバグではありませんが、ある種のとても面倒な問題を起こす場合があります。
再現方法:
これは非常にねじれた uses 節を持つ複雑なプロジェクトにおいて発生する傾向があります。私たちはこれを Pannon-Rex オブジェクトユニットで発見しました。そのユニットでは、initialization セクションでストリーム登録リストのルートノードに nil をセットしていました。不運なことにその initialization は、別のユニットの initialization 節で別のストリーム可能なオブジェクトが登録された後に実行されていました。そのため、ルートノードが nil にセットされたとき、すでに登録されていたオブジェクトが見失われていました。
これはバグだと思いますか?
これはバグではなく、実際は(悪い)言語設計の特徴です。全員が知っておくべき基本的なことは、ユニット内のコードが呼ばれる前にそのユニットの initialization 節が実行されることを当てには出来ないということです。個人的な控えめの意見としては、"Initialization" は "Not_really_initialization" とでも名前を変更するべきだと思います……
|
|
解決策 / 回避方法
|
とても完璧な対処法:
initialization を一切使用しないか、少なくとも initialization セクション内のコードからそのユニット外の呼び出しを避けてください。
Andreas Prucha 追記:
この問題は、ユニットが互いに uses し合っていない場合には発生しません。その場合 initialization セクションを使用し続けることが出来ますし、ユニット外のスコープの呼び出しも可能です。uses し合っている場合でも、プロジェクトファイルの USES 節の順序を呼び出し側が先になるように変更することで、この問題を避けられる場合があります。
|
|