昔の最近の出来事(2003.05)

2003/05/31

出張。

2003/05/30

出張。帰着。ふぅ。

でもまた明日出張(T_T)。

2003/05/29

出張。

2003/05/28

出張。

2003/05/27

出張。

2003/05/26

出張。

2003/05/25

昼頃起床。

何をするでもなく、ぐーたら過ごしてみたり。

何気にチャンネルザッピングしていたら「遅く起きた朝は」が「遅く起きた昼は」 に変わってた。

ちょこーりコーディング。あんま捗らず。

「行列のできる法律相談所」の年齢と出身地のテレコは修正されている模様。

掲示板にて、 gcc-3.xでのcast不具合についての解決方法を御教授 いただきました。
-fstrict-aliasingという最適化オプションを -fno-strict-aliasingで殺せば良いという事でした。 で、確かにOKとなりました(^^)

test> cat cast.c
#include <stdlib.h>
#include <stdio.h>

int main()
{
  double pi ;
  unsigned int *ip ;

  pi=3.141592654 ;

  printf("%f\n",pi) ;

  ip=(unsigned int *)&pi ;
  ip++ ;
  *ip |= 0x80000000 ;

  printf("%f\n",pi) ;
}
  
test> gcc -O2 cast.c
test> ./a.exe 
3.141593
3.141593
test> gcc -O2 -fno-strict-aliasing cast.c
test> ./a.exe 
3.141593
-3.141593
test> gcc --version
gcc (GCC) 3.2 20020927 (prerelease)
Copyright (C) 2002 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

strict-aliasing をキーにgccのinfoを読んでみると、まさにこれ と同じようなコードについての説明がありました。因みに、 gcc-2.95.2の日本語訳infoによると、gcc-2.95.2の-O2では-fstrict-aliasingは 生きていなかったようで、gcc-3.xのmanやinfoによるとgcc-3.xの-O2では -fstrict-aliasingが生きるようになったようです。 ppcのクロスgcc-3.xで同じ事をやると大丈夫だったような気がしたの ですが、gcc-3.3のppcクロスgccでコンパイルした後、ppcsimで実行 してみると やっぱりNGでした(^^; ppc-gccでOKだったと思い込んでいた ので、Intel系specのバグだと思っていたのが、そもそも大間違いだった 様です。
gcc-3.xのinfoを眺めていると、may_aliasというattributeを使用する 事で、部分的にstrict-aliasing を殺すように見せる書き方(正確にはaliasingしない特別な変数型を 定義し それを使用する)ができるようなのですが、サンプルコードその ままではなぜかwarningが出て、効果のほどが判らず。

test> cat cast2.c 
#include <stdlib.h>
#include <stdio.h>

typedef short __attribute__((__may_alias__)) short_a;
          
int main (void)
{
  int a = 0x12345678;
  short_a *b = (short_a *) &a;

  b[1] = 0;

  if (a == 0x12345678)
    printf("error\n") ;

  exit(0);
}
test> gcc -O cast2.c
cast2.c:4: warning: `__may_alias__' attribute directive ignored
test> ./a.exe 
test> gcc -O2 cast2.c
cast2.c:4: warning: `__may_alias__' attribute directive ignored
test> ./a.exe 
error

むぅ。
いや、それにしても奥が深いです。ポインタを使ってどんなアクセスでも 自由自在とか言ってるとハマるという典型的なパターンの様に思い ました。勉強になります。

そんな感じで明日から出張です。

2003/05/24

昼頃起床。

Cygwinのスナップショットなどコンパイル。でも、またしても newlibのconfigureでエラーをぶっこいて停止。つーか、 コンパイルでつっかかるようなものをコミットしないように して欲しいなぁ。

ちょこーりお出かけ。攻殻6とか つじあやの のアルバムとか 購入。
飯を食べながら「こんなハズでは」とか観たり。人の顔を認識 するロボットというのが出ていたのですが、 ビートたけしのものまねそっくりさん(顔はだいぶ違う)を 見せた所、同一人物と判定されて思わず笑ってしまったり。 覚え書き「エニグマ」。

攻殻6鑑賞。ぴひゅー。

「ayu ready?」に武田鉄矢が出てたり。平井賢の 話に大笑い。個人的に、歌い方の話はともかくとして、壊れた時計と 天国に昇るおじいさんの歌詞で、ぶっちゃけ「今はもう動かない おじいさん」の歌詞が、なにゆえ癒し系とされていたのか、 今でも謎に思うこの頃。来週は叶姉妹登場らしいけど、 どうなることやらちょっと興味あり。

2003/05/23

出張。帰着。ふぅ。

タモリ倶楽部。電源コンセントの違いで音響システムの音がどう 変わるかとかいうのをやってた。アンプの接続に使用するケーブル の違いの話だとか、そのケーブルだけで40万円するものがある だとか、2万円以上するコンセントの口だとか、ふーんって感じ(ぉ;。

2003/05/22

出張。

2003/05/21

出張。

2003/05/20

回復せず一日死亡。

2003/05/19

体調悪くなって一日死亡。

2003/05/18

昼頃起床。

何をするでもなく、ぐうたら過ごして一日終了(汗;

「行列のできる法律相談所」などを見ながら飯食ったり。 そういや先週から気になっていたのですが、この番組中でゲストを 紹介する時に出身地と年齢が出るのですが、その時のCGで書かれた 出身地と年齢の枠と、実際の出身地名と年齢がテレコに入っている のですが、誰も気にならないのかしら?

+------+---------+
|名  前|  TANE   |
+------+---------+
|年  齢| ちきゅー|
+------+---------+
|出身地|   3歳   |
+------+---------+

こんな感じ。まぁいいけど。

そんな感じで明日から出張です。

2003/05/17

昼頃起床。

gcc> cat cast.c
#include <stdlib.h>
#include <stdio.h>

int main()
{
  double pi ;
  unsigned int *ip ;

  pi=3.141592654 ;

  printf("%f\n",pi) ;

  ip=(unsigned int *)&pi ;
  ip++ ;
  *ip |= 0x80000000 ;

  printf("%f\n",pi) ;
}

gcc> ./xgcc.exe -I../../gcc/ginclude -S cast.c  
gcc> gcc cast.s
gcc> ./a.exe 
3.141593
-3.141593
gcc> ./xgcc.exe -I../../gcc/ginclude -O2 -S cast.c
gcc> gcc cast.s
gcc> ./a.exe 
3.141593
3.141593
gcc> ./xgcc --version
xgcc (GCC) 3.3
Copyright (C) 2003 Free Software Foundation, Inc.
This is free software; see the source for copying conditions.  There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

むぅ、これぁ もう直らないものだと思った方が良いのかのう。

うむぅ! グラビアの方はその手法がよく判らず怪しげでしたが、 こちらは力技って感じですな。でもどうせなら、もっと呆れるくらい 力を込めて欲しいかも。例えば、モザイク個所を最小にする為に、 Photshopを使って1フレームずつ人力で処理したという アダルトビデオがありましたが、そんな感じでブルーバックの全フレーム を全て手作業で抜いて、超高精度にモデリングされたリアルタイムCG背景に 合わせるとか。
あと、360度全方向にカメラを配置すると反対側のカメラが映り込むのが 問題とありましたが、例えば逆に十分に離れた位置からズームで狙えば、 画質はともかく反対側のカメラが映り込むという事は気にしなくても 良いとか、そういうのは無しなのかなぁとか思ったり。どうせ全方向 360度から同時に狙う前提だったら、アングルは気にしなくて良い訳ですし。
そんな感じで、顔と名前が一致しない場合は、 乳と名前を一致させるとか(<アホか!)、顔と乳を一致させるとか (<それは違うだろ)、組合わせを変えてみるのはどうですか?(ぉぃ;

Cygwinを先日のスナップショットに入れ替え。で、gccのppcクロス ビルドによるlibstdc++ をビルドした所、sh.exeのズッコケが発生 しなくなってしまいました(^^;。configureを最初からやり直しても、 gcc-3.3のppcクロスビルドを行なってもエラー無くビルド完了。 むぅ、騙されているかも知れないけど、なんとなく解決という事に してしまうか......
で、make installしたら途中でエラー(^^; sh.exeをbash.exeで 代用したら、なんとなく同じ所でエラーしているような気がする のですが、そのまま通過したのでOK?(?_?)。POV-Ray 3.5のコンパイル には成功。ppcsim実行も取りあえずOKそう。

cast問題対応の為、コードを書き換える事を考えてみたり。所が、 確認の為に実験コードを書いた所、なにか嫌な感じがしてみたり。

test> cat lltest.c
#include <stdlib.h>
#include <stdio.h>

int main()
{
  double pi ;
  unsigned long long int *ip ;

  pi=3.141592654 ;

  printf("%f\n",pi) ;

  ip=(unsigned long long int *)&pi ;
  *ip = 0x8000000000000000 ;

  printf("%f\n",pi) ;
  printf("%08x_%08x\n",(unsigned int)(*ip>>32),(unsigned int)(*ip & 0xffffffff)) ;
}
test> gcc -O lltest.c
test> ./a.exe 
3.141593
-0.000000
80000000_00000000
test> gcc -O2 lltest.c
test> ./a.exe 
3.141593
3.141593
80000000_00000000

何が嫌かと言いますと、この結果を見ると、-O2の時は double piが floating registerに乗っている為、その間の別のポインタによる同領域の メモリ参照が空ぶっているか、そもそも定数扱いになっている様に見えます。 定数扱いになっているのであれば、まぁ、最悪書き方 で回避できると思うのですが、floating registerに載っているイメージ の場合、更に似たケースを拡大させると、int型であっても、レジスタ に載る可能性がある変数は、ポインタで参照してはいけない予感が してしまいます。少なくとも、この現象に最初にぶつかった、昔の ppcsimのコードは こんな感じだったのですが、 この関数内では、この後すぐにreturnしてしまう為、 mres->FPR[fd].fを参照する事はありません。なので、そもそも *fpr_uに対する操作自体が完全に空ぶっていて、演算結果が闇に葬り 去られている感じになっていた為、定数化説は当てはまりません。 従って、ある型の 変数を異なる型のポインタで参照する事はNGと言えると思います。 最悪、浮動小数点系型と整数系型の間だけは相互にポインタ参照 うまくいかないのであれば、救い様が........無いか?どうやって 書けば良いのか判らん(^^; あぁ、それよりもIntel系の命令セットの読み方が よく判らんので、定数化説とポインタ参照NG説の区別が付かない のがダメダメなのですが(汗;

取りあえず、long long intを使って型変換を行なう事で、 エンディアンの違いによるコードの切り替えを無くしてみたり。

*** 380,392 ****
    
    if( DO_EXEC_INST(mode) ){
      if( rd!=0 ) return(NOT_IMPLEMENTED_OP) ;
!     fpr_l = (unsigned int *)&mres->FPR[fd].f ;
! #ifdef HOST_ORDER_IS_LITTLE_ENDIAN
!     *fpr_l= mres->FLGR.fpscr ;
! #else
!     fpr_l = fpr_l+1 ;
!     *fpr_l= mres->FLGR.fpscr ;
! #endif
      mres->pc += 4 ;
    }
    
--- 353,360 ----
    
    if( DO_EXEC_INST(mode) ){
      if( rd!=0 ) return(NOT_IMPLEMENTED_OP) ;
!     cast_ll = (unsigned long long int *)&mres->FPR[fd].f ;
!     *cast_ll= (unsigned int)mres->FLGR.fpscr ;
      mres->pc += 4 ;
    }
    
***************

だんだん、gccのVer1系とか、古いコンパイラではコンパイルで きなくなって来ている予感。でも、 C99規格の マクロによる可変長引数渡し を行なっている時点で、gcc-2.7系列でのコンパイル も通らなくなっているので まぁいいか。

2003/05/16

出張。帰着。ふぅ。

gcc-3.3がリリースされた様なので、早速ダウンロード....終らねぇ.....
Cygwinのスナップショットもダウンロード.....更に終らねぇ(ぉぃ;

まずは、Cygwinのbuildから。一つ前のはnewlibのconfigureでエラーしていましたが、 今回は問題なくbuild完了。
gccは以下の手順でCコンパイラのみbuild。

bzip2 -dc ~/down/gcc-3.3.tar.bz2 | tar xvf -
cd gcc-3.3
mkdir build
bash ./contrib/gcc_build -o build -d ~/develop/gcc_cyg/gcc-3.3 -c '--prefix=/usr  --enable-languages=c' build

何故かオリジナルのsh.exeだとスクリプトがエラーしたので、bash を使用しました。

終らず........眠くて死亡。

2003/05/15

出張。

2003/05/14

出張。

2003/05/13

出張。

2003/05/12

出張。

2003/05/11

起きたら夕方。寝過ぎ。

シェルのずっこけを簡単なプログラムで再現できないか試してみるが再現せず。

大往生やったりしてまったり過ごす。それにしても上達しねぇ〜(T_T)

そんな感じで明日から出張です。

2003/05/10

昼前起床。ちょっこり出社。

秋葉方面へ。すごく久しぶりに秋葉の書泉ブックタワーに行ったのですが、 隣に建物が建っていてビックリした。再開発でごちゃごちゃやっている ようです。それよりも駅の中の改札までの順路が変わってて、混雑が少し 解消されているのは良かったです。
やり込みのDVDを探して店をいくつか回ったのですが、 なにせジャンルがアレなものですから、まずどこを見れば良いのかから判らない。 結局、発見することはできず。

神田方面を回った時に、村田蓮爾氏の画集にダイブしてみました。 奇跡的にも近所の本屋に置いてあったりしたのですが、値段が高すぎて 腰が引けていたのです(^^; で、今回のはバインダー式になっていて、 ページがめくりやすくなってます。思ったよりも古いイラストがメインで 収録されていたので少しガッカリ。比較的、最近の快楽天の表紙は芸風が 少し変わった感じがしていたので、それらと合わせて見られる事を 期待していたのですが、それはそれとして。あぁ、でも、前回の画集は 見ていると分解しそうだったので、あんま見てなかったのですが、 今回のも、その辺の本の山に積んどいて、気が向いた時に見るには 装丁が凝り過ぎていて少しイマイチ(<ちゃんと本棚に入れろよ)。 そうでなければ穴が開くほど見られるのですが(^^;

Cygwinのスナップショットが出ていたのでbuild。でも、newlibの configureでエラー。winsup/cygwin/cygthread.ccに手が入っている ようだったので、もしかすると、先日からのshずっこけが直るかも と期待を込めて、20030426のスナップショットで、cygthread.ccだけ 差し替えで再コンパイル。でも、シェルずっこけは解決せず。へこり。
それよりもMailingListで話題になりかけたmmap()バグの話が、解決を みないまま自然消滅しかかっていそうなのが気になるのですが(^^;;

2003/05/09

出張。帰着。ふぅ。

shをソースからコンパイルしてみることに。でも、結果は変わらず。

眠くて死亡。

2003/05/08

出張。

2003/05/07

出張。帰着。でも明日また出張。

出張帰りの駅のホームで、後ろに居た二人の会話。

A:「.....気を付けないとあぶないよ」
B:「いやぁ、絞め技くらいじゃ死んだりしないって」
B:「やっぱ押さえ込むには絞め技が有効だからね」
一体 何の話だよ?!

西友で生活備品のお買い物。その時、ラクガキ用に白帳を買おう としたのですが、ふと目をやったコピー用紙が思いのほか安かった ので、そちらを買ってみる事に。どうせ捨ててしまうものなので、 安いに越したこと無し。

CygwinのMailingListでmmap()で同じポインタを返すバグ報告が 上がっているようです。やった!これで 正式に修正されるよ!と思ったのですが、具体的な再現コード 待ちになっている模様。あぅ、早く出してあげてください!くわっ! あぁ、でも確かにWin2000やXPだとOKというのはよく判りませんなぁ。
それにしても、ソースからbuildしていちいちデバッグして原因を 追求する人って、意外と居ないのだなぁと思ったりして。 そんな暇な奴ぁいないって事ですか(^^; 私?んー、ってゆーかぁー、えいごぉー、わかんないしぃー(ぉぃ

libstdc++のconfigureをオリジナルのsh.exeで実行するとconfigure に失敗する件の調査の続き。
何気にgccをconfigureからやり直したら、libstdc++のconfigureから 実行してもずっこけが再現する様になりました。どうやらltconfigが エラーを返して、呼び出し元のconfigureがエラー終了するという 順番の様子。で、ltconfigをsh実行する際に、straceを噛ましてみた 所、やっぱり途中でstraceがハングします。Cygwin本体に 問題がある為、straceがうまく動かないと考えるのが妥当な気がして でました......
思いつきで、snapshotからbuildしたstraceを使用してみた所、 straceがハングる事なくエラーが再現しました。という事は Cygwin本体はOK? でも、例外を受けてshが死んだと思われて いたのですが、straceの結果からは例外を受けたような振るまいが 見られず。一応、shの持つ最後の子プロセスがゾンビ状態 になり、最終的に消滅した所で、全threadのクリーニング 終了で、プロセス退出となっているので、straceの結果からも問題 無く終了している様に見えます。むぅ、こうなったら、根拠の無い 必殺技だけど、shを再コンパイルしてみるか?

2003/05/06

出張。

2003/05/05

昼前に起床。

先日のsh問題をテストする為、gccのppcクロスmakeをほったらかし ておいたのですが、libstdc++のconfigureでshが死んでエラーで 止まってました。以前のfork()問題の時もそうだったのですが、 libstdc++のconfigure実行は かなり高い負荷テスト効果がある みたい(^^;
さておきstackdumpを見てみると、VirtualFree fail になっていて、結局、オリジナルのsh.exeでもエラーすることはする という感じです。比較的短い時間でエラーするので 追いかけようかとしたのですが、configure実行が makeの中に包まれている為、どういう引数でconfigure実行されて いるのか判らず。config.statusも残っていないし、make -nで見ても、 if文だらけの長大なスクリプトがメッセージ出力されるだけで、 最終的にどう実行したのかさっぱり判らず。しかた無しに strace make を実行 してみた所、途中でstraceがハングったりして結局追いかけられず。
それにしても、こうもあっさり悩まされるハメになるとは。 もう少し耐えてくれよぅと思ったりして。

で、sh.exeをbash.exeにすると通ったりする罠。一応これでconfig.status が出来あがるので、これの先頭の方に書かれているconfigure実行時 オプションをコピペして、再度configure実行した所、オリジナルの sh.exeでもズッコケが再現しない罠(汗;むぅ。

表紙絵を描いてみたり。

むぅ、モーショングラビア.......怪しげなテクノロジーに そそられますが(<そそられるの?)、まだまだ(<って何が?)。
いやでも、MEGUMIより後は、せくすぃではあるのですが、イマイチ パッとしないのですよね。4人まとめて入っていれば 良いのに!(<って そこかよ....)

LASTEXILEとか。3Dパートの動きについて色々言われているのが やっと判った気が(先週、初めて見た時は飛ばなかったので イマイチよく判ってなかった(^^;)。個人的には、なんてゆーか、こう、 まず、ガンシップの見た目が飛ぶように見えない事から違和感を感じると 言いますか。 元々浮遊感の無いデザインに思えるのに、あの軽い感じの動きが付いている 訳ですから、余計になんか、こう、微妙な感じに見えるような気がします。 翼やジェットのノズルでも付いていれば、見た目に飛ぶ感が出るので、 少々効果がヘボくても、脳内補完でうまく飛んでる様に見えると思うのですが、 あのミサイルみたいので、コントローラブルに飛ぶサマっちゅうのは 私の脳ミソではイマイチ補完できません(^^; ミサイルの様に飛ぶの なら判りますが、絵はそう動いていないので、なんか不自然に見える というか、そんな感じ。それよりも、話の進みがタルいのでちょっと 退屈。

2003/05/04

日が沈みかけた時間に起床(汗;。

mmap()の調査とか。先日までの調査で、二回に一回mmap()が成功し、 二度目のmmap()で変なアドレスが返る事が判っていますが、二度目の mmap()の際はメモリページに使用している事を示す フラグをセットしているようです。所が、デバッガで追いかけていると、 一度目のmmap()では、MapViewOfFileEx()でメモリ確保に成功した後、 このうちの使用するサイズ分だけ使用中を示すフラグをセットする 必要がありそうですが、それを行なっていない無い様に思えました。
という点から推測。一度目のmmap()でMapViewOfFileEx()による確保を 行なった後、その確保したエリアを使用している事を示すフラグを 付け忘れている。二度目のmmap()では既に確保されているメモリ ブロックのうち、空きがあればそこからメモリを割り当てる仕組み になっているようですが、一度目のmmap()で割り当てた領域が、 フラグの付け忘れにより、まるまる未使用に見えるため、そこから 割り当ててしまう。結果、二度目のmmap()でも一度目のmmap()と 同じメモリ領域のポインタが返る。三度目のmmap()を実行すると、 二度目のmmap()により使用フラグが正しくセットされている為、 新たにMapViewOfFileEx()でメモリ確保を行なうが、一度目と 同じく使用フラグをセットし忘れる。以下、同じ動作の繰り返し。
という点を踏まえてmmap.ccのソースを2003/01頃の物と比べてみると、

cygwin> sdiff cygwin-snapshot-20030119-1/winsup/cygwin/mmap.cc cygwin-snapshot-20030426-1/winsup/cygwin/mmap.cc | less -N
     612   /* Insert into the list */                                      /* Insert into the list */
     613   mmap_record *rec = l->add_record (mmap_rec);                |   mmap_record *rec = map_list->add_record (mmap_rec, off, len
     614   if ((off = rec->map_map (off, len)) == (__off64_t)-1)       |   caddr_t ret = rec->get_address () + (off - gran_off);
     615     {                                                         <
     616       fh->munmap (h, base, gran_len);                         <
     617       l->erase ();                                            <
     618       syscall_printf ("-1 = mmap()");                         <
     619       ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK | WRITE_ <
     620       return MAP_FAILED;                                      <
     621     }                                                         <
     622   caddr_t ret = rec->get_address () + off;                    <
     623   syscall_printf ("%x = mmap() succeeded", ret);                  syscall_printf ("%x = mmap() succeeded", ret);
     624   ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK | WRITE_LOCK     ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK | WRITE_LOCK
     625   return ret;                                                     return ret;
     626 }                                                               }

てな感じの差分があり、2003/01頃の(左側)は最後にページ使用のマップを 塗りつぶすrec->map_map()が実行されていますが、最新のは それが無いみたい。

という訳で、mmap.cc:mmap64()に2003/01頃の前述差分をパッチしてみた所、 同じメモリ領域を二重にmmap()で返してしまう不具合は解消しました(^^)v

*** mmap.cc.org Thu Apr  3 10:28:54 2003
--- mmap.cc     Sun May  4 23:51:24 2003
***************
*** 576,581 ****
--- 576,589 ----
  
    /* Insert into the list */
    mmap_record *rec = map_list->add_record (mmap_rec, off, len);
+   if ((off = rec->map_map (off, len)) == (_off64_t)-1)
+     {
+       fh->munmap (h, base, gran_len);
+       map_list->erase ();
+       syscall_printf ("-1 = mmap()");
+       ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK | WRITE_LOCK, "mmap");
+       return MAP_FAILED;
+     }
    caddr_t ret = rec->get_address () + (off - gran_off);
    syscall_printf ("%x = mmap() succeeded", ret);
    ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK | WRITE_LOCK, "mmap");

これで良いかどうかは良く判りませんが、先日の再現プログラムも、 ppcsim実行も、不具合は解消できました。ふぅ。
パッチ前のDLLで、一発目のmalloc()によるmmap()に成功した後、free()すると mmap()されていない領域をmunmap()して死にそうな感じがしたので、そのような プログラムを書いてみたのですが、死ぬことはありませんでした。恐らく、 malloc()でのメモリ確保では、一度確保するとしばらくの間は、再malloc() に備えてOS(CygwinではDLLを介してWindowsカーネル)に、すぐにはメモリを 返却しない機構のおかげ(せい?)で、すぐには(もしかすると永久に) munmap()が実行されない為だと思われます。

「SHOWBIZ COUNTDOWN」でマトリックス・リローデッドのメイキングが ちょろっと流れてました。なんかスゲー、そんな感じ。

configureでcygthread::terminate_threadがVirtualFree failになる件 の調査。 fork()ずっこけ問題の原因が 解明されるまでは、bash.exeをオリジナルのsh.exeの代わりに使用する事で、 configureが通ったりしていたので、実は今の今まで/bin/sh.exeは/bin/bash.exe そのものでした。で、この辺が悪さしているのではないか?と思い、最新の bash.exeをsh.exeにコピーしてgccのconfigureを実行してみました。 結果は変わらず。所が、オリジナルのsh.exeでconfigureを実行した 所、VirtualFree failのメッセ―ジは出なくなってしまいました(^^; しかも、bashを使ってのconfigure実行中、/tmpにsh-thd-*という一時ファイル が大量に生成されたままになっていたのですが、これも発生しなくなりました(^^;;
という事で、bashのスクリプト実行モードに何かしら問題がありそう な予感がするのですが、結果オーライという事で深く追求しない事 にしました。でも、しばらくするとまた何かの拍子に同じ現象に悩まされ そうな予感がしなくもありませんが、それはそれとして。
あぁ、そういやrxvt起動したbashがいきなり普通に終了するという 怪奇現象が稀に発生する場合があったのです(MailingListでもそのような 報告が上がっていたようです)が、もしかすると それとの関係が あるのかも......と思っただけ。根拠無し。

2003/05/03

昼頃起床。ふんにゃらテレビなどを観て過ごす。

日が暮れた頃に飲みに出撃。渋谷到着でKOJIさんに連絡取ろうとした 所に、偶然Keiさんに発見されてみたり。携帯リモコンでKOJIさんと 落ち合い。まさちくさんは本日はNGという事で連絡を受けたり。で、 今日は渋谷で鉄板焼き.......のハズが店が閉まっていて死亡。 徘徊して店を探してバーで飲み。しばらくして、たぼさん登場。 で、色々話して店変えて話して、午前3時過ぎ(汗;。 Keiさん脱落気味だったので、一緒にタクシー帰り。お疲れさま でした。

急激に眠くなって撃沈。

2003/05/02

今日はお休み。

先日のmalloc()でNGの件を追跡調査。以下の様にコードを書き換えて みた所、変な結果になりました。

test> cat malloc_test.c
#include <stdlib.h>
#include <stdio.h>

//#define MALLOC_SIZE 0x00fffff4
//#define MALLOC_SIZE 0x00fffff5
#define MALLOC_SIZE 0x01000000

int main()
{
  int i,j ;
  unsigned char *p[8] ;
  
  printf("malloc size = 0x%08x\n",MALLOC_SIZE) ;

  for( j=0 ; j<8 ; j++ ){
    p[j]=malloc(MALLOC_SIZE) ;
    if( p[j]==NULL ){
      printf("malloc error %d\n",j) ;
      exit(-1) ;
    }
    for( i=8 ; i>0 ; i-- ){
      printf("%02x ",*(p[j]-i)) ;
    }
    printf("\n") ;
  }

  for( j=0 ; j<8 ; j++ ){
    printf("%d : 0x%08x\n",j,(unsigned int)p[j]) ;
  }

  exit(0) ;
}
test> gcc -g malloc_test.c
test> ./a.exe 
malloc size = 0x01000000
00 00 00 00 02 10 00 01 
00 00 00 00 02 10 00 01 
00 00 00 00 02 10 00 01 
00 00 00 00 02 10 00 01 
00 00 00 00 02 10 00 01 
00 00 00 00 02 10 00 01 
00 00 00 00 02 10 00 01 
00 00 00 00 02 10 00 01 
0 : 0x86ec4008
1 : 0x86ec4008
2 : 0x87ed4008
3 : 0x87ed4008
4 : 0x88ee4008
5 : 0x88ee4008
6 : 0x89ef4008
7 : 0x89ef4008

因みに最初の16進ダンプのようなものはmalloc()関数内で 表現されるチャンクのヘッダです。02 10 00 01 は0x01001002 で16MB+0x1002B 分を確保しているようです。 で、何が変かと言いますと、必ず失敗する感じではなく、二回に一回は 成功するという点です。16MB以上割り当てられないのであれば、 常に変になっても良さそうです。
と、ここまで調べていきなり思い出したのですが、Cygwinには システムコールなどのカーネル実行イベントをトレースするための straceというコマンドが存在します(SunOS系ではtrussと呼ばれてる コマンドに似たものです)。これの存在をすっかり忘れてました(^^; それで実行結果を見てみると、以下の様にmmap()を使ってメモリ割り当て を行なうようです。

test> strace ./a.exe       
**********************************************
Program name: C:\TANE\DEVELOP\CYGWIN\TEST\A.EXE (1201267)
App version:  1003.22, api: 0.78
DLL version:  1005.0, api: 0.84
DLL build:    20030426 23:49:26SNP
OS version:   Windows 98-4.10
Heap size:    402653184
Date/Time:    2003-05-02 22:13:35
**********************************************
  :
  :
  385  172992 [main] a 1201267 mmap64: addr 0, len 16781312, prot 3, flags 22, fd -1, off 0
 1366  174358 [main] a 1201267 fhandler_disk_file::mmap: 86EC4000 = MapViewOfFileEx (h:F4, access:2, 0, off:0, len:16842752, addr:0)
  741  175099 [main] a 1201267 mmap64: 86EC4000 = mmap() succeeded
  348  175447 [main] a 1201267 mmap64: addr 0, len 16781312, prot 3, flags 22, fd -1, off 0
  207  175654 [main] a 1201267 mmap_record::map_map: map_map (fd=-1, off=0, len=16781312)
  394  176048 [main] a 1201267 mmap64: 86EC4000 = mmap() succeeded
  320  176368 [main] a 1201267 mmap64: addr 0, len 16781312, prot 3, flags 22, fd -1, off 0
  940  177308 [main] a 1201267 fhandler_disk_file::mmap: 87ED4000 = MapViewOfFileEx (h:F8, access:2, 0, off:0, len:16842752, addr:0)
  330  177638 [main] a 1201267 mmap64: 87ED4000 = mmap() succeeded
  349  177987 [main] a 1201267 mmap64: addr 0, len 16781312, prot 3, flags 22, fd -1, off 0
  211  178198 [main] a 1201267 mmap_record::map_map: map_map (fd=-1, off=0, len=16781312)
  345  178543 [main] a 1201267 mmap64: 87ED4000 = mmap() succeeded
  682  179225 [main] a 1201267 mmap64: addr 0, len 16781312, prot 3, flags 22, fd -1, off 0
  979  180204 [main] a 1201267 fhandler_disk_file::mmap: 88EE4000 = MapViewOfFileEx (h:FC, access:2, 0, off:0, len:16842752, addr:0)
  432  180636 [main] a 1201267 mmap64: 88EE4000 = mmap() succeeded
  429  181065 [main] a 1201267 mmap64: addr 0, len 16781312, prot 3, flags 22, fd -1, off 0
  357  181422 [main] a 1201267 mmap_record::map_map: map_map (fd=-1, off=0, len=16781312)
  390  181812 [main] a 1201267 mmap64: 88EE4000 = mmap() succeeded
  325  182137 [main] a 1201267 mmap64: addr 0, len 16781312, prot 3, flags 22, fd -1, off 0
  982  183119 [main] a 1201267 fhandler_disk_file::mmap: 89EF4000 = MapViewOfFileEx (h:100, access:2, 0, off:0, len:16842752, addr:0)
  337  183456 [main] a 1201267 mmap64: 89EF4000 = mmap() succeeded
  399  183855 [main] a 1201267 mmap64: addr 0, len 16781312, prot 3, flags 22, fd -1, off 0
  213  184068 [main] a 1201267 mmap_record::map_map: map_map (fd=-1, off=0, len=16781312)
  339  184407 [main] a 1201267 mmap64: 89EF4000 = mmap() succeeded
  :
  :

で、見ててハタと気づいたのですが、0x86EC4000について見ると、 二つのmmap()の戻り値と思わしき物が存在します(mmap64: xxxxxxxx = mmap() succeeded)。 最初のsucceededではMapViewOfFileEX()というWinAPIを使用した 結果が成功した事がうかがえます。所が、二つ目のsucceededは map_record::map_mapというCygwin内のルーチンが返した値の 様に見えなくもありません。もしかするとこの辺の違いに 秘密がありそうな予感。

お出かけ。本屋へ。探しても見つからなかった「高校アフロ田中」 をやっと発見。他、ファミ通WaveDVDとか。

飯食べながらファミ通DVD鑑賞。F-ZERO GC/F-ZERO ACの動画像を 見たり。グラフィックがとんでもなく綺麗なのですが、動きの方が あまりにも速過ぎてゲームにはついていけそうもない予感(^^; 3D酔いはしないタイプなのですが、なんか見てて酔いそうな感じ。 やり込みは今回もスゴイです。マリオカート64のやり込みなので、 ゲーム自体をやった事が無いのですが、その走りっぷりは やった事なくても「スゲー」と思わせるものでした。発売から 7年経ったゲームでもやり込みとして送られてくるのもスゲーと 思いました。

KOJIさんとお電話、VirtualQuery()とかVirtualFree()に関して 色々、御教授してもらったり。そんな感じで明日飲みに行く事 で決定。

ふにゃふにゃと追っかけ。
メッセージなどから、winsup/cygwin/mmap.ccにmmapの本体が あるようだったので眺めてみました。どうやらmmap64()内の 523行目辺りがそれっぽいです。

     514       if ((rec = map_list->match (off, len)) != NULL)
     515         {
     516           if ((off = rec->map_map (off, len)) == (_off64_t)-1)
     517             {
     518               syscall_printf ("-1 = mmap()");
     519               ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK|WRITE_LOCK, "mmap");
     520               return MAP_FAILED;
     521             }
     522           caddr_t ret = rec->get_address () + off;
     523           syscall_printf ("%x = mmap() succeeded", ret);
     524           ReleaseResourceLock (LOCK_MMAP_LIST, READ_LOCK | WRITE_LOCK, "mmap");
     525           return ret;
     526         }
     527     }

522行目の戻り値retの内わけを調べてみると、offは0になって いました。offは516行目のrec->map_map()で得られた値に なりますが、これが失敗するとmmap()自体が失敗してしまいます。 straceの結果から言うと、MapViewOfFileEx()で実際に割り当てている サイズは本当に指定した16MB分しか割り当てていないので、 off=rec->map_map()の値が正しいか否かというよりは、 ここら辺のルーチン自体を通る事が間違いのような気がします。
因みに、一つのノードが64KBのリストを合計が16MBくらいになる まで成長させた場合、mmap()は実行されませんでした。heapの 拡張も行なっていないようなので、この範囲内で使っている分には 全く問題が出ないものと思われます。

あと、malloc()するサイズを0x00100000とか、安全とされている サイズにして、何度もこのサイズで割り当てる(ノードが0x00100000バイトの リストを作る)と、mmap()内でSegfaultしてしまうバグ(今回は 合計374MBくらいの割り当てで死んだ)を見つけて しまいました(^^;

(gdb) run
Starting program: /cygdrive/c/tane/develop/cygwin/test/a.exe 
malloc size = 0x00100000
   0 00 00 00 00 09 00 10 00 
  :
 374 00 00 00 00 09
Program received signal SIGSEGV, Segmentation fault.
0x6103ac81 in list::add_record(mmap_record, long long, unsigned long) (this=0x18872be8, r={fdesc_ = -1
, mapping_handle_ = 0xfc, devtype_ = 0, access_mode_ = 2, offset_ = 0, size_to_map_ = 1114112, base_ad
dress_ = 0x87a06000 "", map_map_ = 0x0}, off=0, len=1052672) at ../../../../winsup/cygwin/mmap.cc:298
298       recs[nrecs] = r;
Current language:  auto; currently c++
(gdb) where
#0  0x6103ac81 in list::add_record(mmap_record, long long, unsigned long) (this=0x18872be8,r={fdesc_ =
 -1, mapping_handle_ = 0xfc, devtype_ = 0, access_mode_ = 2, offset_ = 0, size_to_map_ = 1114112, base
 _address_ = 0x87a06000 "", map_map_ = 0x0}, off=0, len=1052672) at ../../../../winsup/cygwin/mmap.cc:
 298
#1  0x6103b5bd in mmap64 (addr=0x0, len=1052672, prot=3, flags=34, fd=-1, off=0) at ../../../../winsup
/cygwin/mmap.cc:579
#2  0x6103b93c in mmap (addr=0x0, len=1052672, prot=3, flags=34, fd=-1, off=0) at ../../../../winsup/c
ygwin/mmap.cc:589
#3  0x610389a5 in sYSMALLOc(unsigned, malloc_state*) (nb=1048584, av=0x61117a10) at ../../../../winsup
/cygwin/malloc.cc:3069
#4  0x61038bcc in dlmalloc (bytes=411511784) at ../../../../winsup/cygwin/malloc.cc:3722
#5  0x61039a26 in malloc (size=1048576) at ../../../../winsup/cygwin/malloc_wrapper.cc:132
#6  0x00401163 in main () at malloc_test.c:20
(gdb) 

ここん所を見てみると、

     290 mmap_record *
     291 list::add_record (mmap_record r, _off64_t off, DWORD len)
     292 {
     293   if (nrecs == maxrecs)
     294     {
     295       maxrecs += 5;
     296       recs = (mmap_record *) realloc (recs, maxrecs * sizeof (mmap_record));
     297     }
     298   recs[nrecs] = r;
     299   recs[nrecs].alloc_map (off, len);
     300   return recs + nrecs++;
     301 }

となっているのですが、realloc()が失敗したけどそれをチェック せずそのまま使っているのが原因のような気がします。

2003/05/01

出張。帰着ふぅ。

眠くて死亡。


TOP PREV