こんにちは、川合です。 FORM-Akkie さんは 2003/11/22 23:41:06 の「[OSASK 6688] FORM: Re: go_0020b.」で書きました: >> そうかなあ。>ディスクよりも時間 osaskgoに限って言えば、1MBを >>超えるサイズは時間以上に問題だろうと思うのですが・・・。 > 大きすぎるのは確かに問題ですけど、同じ五日間かけるなら、 >数パーセントしか縮まないよりは数倍速くなる方がよいと思う >のです。機能(?)密度もぐっと上がりますよね? これはまったくそのとおりです。 こういうのは機能密度とは違う気がしますが、いいたいことはよくわ かります。 >> もし時間がかかって困るということなら、最後のリリース時以外には >>いつも、bim2binのオプションに「maxdis:1k」とでも書いておいてくだ >>さい(orgを作るときも、binを作るときも)。見違えるほど速くなりま >>す。 > なるほど。圧縮率を下げるという方法がありましたか。実践的 >だなあ。……でもせこい気が(^^; はい、せこいです。でも、時間のロスだあ、と叫ぶような状況は回避 できるかと。もちろん一番いいのは、圧縮ルーチンをまともにしてさら にmaxdis指定を活用することであります。 >> そもそも、CやC++のstatic変数は初期値を指定しなければ初期値は全 >>て0とするのが仕様で、その意味ではCでbss領域が生成されることは普 >>通ありません(GCCとかは、参照される前に書かれるかどうかを慎重に >>チェックして、大丈夫と分かったものだけにbss属性をあたえていた、 >>はず・・・ということで、多くのケースではうまく判定できず、dataセ >>クションになります)。 > 私の記憶が確かなら、staticでなくてかつ初期値のないグロー >バル変数はbss領域に入ります。すると……mallocしなくても その記憶は僕の持っている書類と食い違っています。残念ながら。 ANSIのプログラミング言語C, X3.195-1989の解説(K&Rの付録)によ ると、次のような記述があります。 --- A4.1 記憶クラス 記憶クラスには自動的と静的(static)の二つがある。(中略)自動 的なオブジェクトはあるブロックに局所的なもので、そのブロックから 出ると捨てられてしまう。ブロックの中で宣言を行なうと、記憶クラス が指定されていないか、あるいはauto指示子が指定されていれば自動オ ブジェクトが創られる。(中略) 一方、静的なオブジェクトはブロックに局所的であってもよいし、す べてのブロックの外部にあってもよいが、いずれの場合も、その値は関 数やブロックから出たり入ったりする間も保持される。ある関数プログ ラムを含むブロックも含めてブロックの中では、静的なオブジェクトは キーワードstaticで宣言する。関数定義と同じレベルですべてのブロッ クの外側で宣言されたオブジェクトは常に静的である。staticキーワー ドを使えば、それらはある特定の翻訳ユニットに対して局所的にできる 。これで内部リンケージが与えられるわけである。明示的な記憶クラス を省くか、あるいはキーワードexternを使うことにすれば、それらはプ ログラム全体に対して広域的になる。これが外部リンケージである。 A8.7 初期化 (前略)明示的に初期化されない静的なオブジェクトは、それに定数 0が代入されたかのように初期化される。明示的に初期化されない自動 オブジェクトの初期値は、不定である。(後略) --- 以上の記述にしたがえば、グローバル変数宣言においてstaticキーワ ードつけるかどうかは、リンケージの範囲を指定するためのもので、初 期値の振る舞いを左右するためのものではありません(staticと書いて も書かなくても静的変数、つまり僕がいうところのstatic変数になるわ けです)。したがって、 #include <stdio.h> int g[100]; int main() { int i, s = 0; for (i = 0; i < 100; i++) s += g[i]; printf("%d\n", s); return 0; } の結果は、常に0でなくてはならないのです(配列にする必要はないん ですけどね)。 しかし、I.Tak.さんの記憶が間違っているということにはなりません 。そのコンパイラは、bssが自動で0初期化されると想定して、そのよう なコードを出力したのかもしれないからです。 もし時間があれば、上記プログラムのgの宣言にstaticを付けたり外 したりして、生成されるアセンブラソースを観察してみてください。 と書きましたが、ついでなので、gcc-3.2.3ベースのMinGWで観察して みました。 ・int g[100];の場合: .comm _g, 400 ・static int g[100];の場合: .lcomm _g,400 ・int g[100] = { 0 };の場合: .globl _g .data .align 32 _g: .long 0 .space 396 ・static int g[100] = { 0 };の場合: .data .align 32 _g: .long 0 .space 396 こうなりました。なおGOでは、初期値を一つも指定しなくてもdataセク ションに回されて、 ..globl _g .data .balign 16 _g: .space 400 となります。 asの擬似命令の説明(*1)によると、.space 400は400バイトのゼロフ ィルを意味します。不定値ではありません。また.lcommについては、 bssセクションに確保されて、ランタイムで0クリアされると明記され ています。.commの説明には、uninitialized memoryを割り当てるとい う説明しかなく、ゼロクリアはasとしては規定していないようです。に もかかわらず、MinGWが.commを使うのは、win32ではゼロクリアしたメ モリをくれることを仮定できるからなんだろうと思います。 ちなみに今回のテストで判明したことですが、GCCはろくなチェック をしないで全部bssに回していました。これは僕の[OSASK 6685]の記述 が間違っていたことを意味します。チェックしていたのは、lcc-win32 だったような気がします。 *1: http://sources.redhat.com/binutils/docs-2.12/as.info/Pseudo-Ops.html#Pseudo%20Ops >グローバル変数を使えばいいじゃねえか、ということになるわけ >です、私の発想では(大規模なツールで乱用すると危険ですが)。 >そうするとmallocの処理が無くなったり引数が減ったりして >うれしいかなあ。微妙ですか。でもこれだと引数が全て定数に >なるのでlib_execcmd()が使いやすいんですよ。 結局、これをやるには、Cで初期値不定のstatic変数を確保する新た な文法を確立する必要がありそうです。単にmalloc減らしやlib_execcm dの全パラメータ定数化を目指すなら、普通に静的変数を取ればいいで すが、サイズがでかいとその分だけdataセクションの肥大化を招きます 。しかしまあ10MBだとしてもtek0で数バイトにまとまるので、これもそ れほど問題ではないと思っているのですが・・・。 それでは。 -- 川合 秀実(KAWAI Hidemi) OSASK計画代表 / システム設計開発担当 E-mail:kawai !Atmark! imasy.org Homepage http://www.imasy.org/~kawai/