日付越え前に帰着。
何やらうまくいかないのを調べたり。
遅めに帰着。
ちょろりコーディング。
昼過ぎ起床。
もそもそとコーディング。
Webを検索していると、高校生とかでD言語を使っている人もちらほら居るようです。
しかしなんでまたD言語を?と思わなくもなかったり(^^;; なんとなくD言語関連ページ
を検索するとゲームを作っている割合が他の言語に比べて特別に多いように見える
のがその要因かな?と思ったりも。でも、実際には2004〜2006年頃に色々作られたのが
ピークで、今はそれほど色々作られている感じでは無いような気も。また、相対的に
ゲーム以外のものを作っている例が極端に少ないのも錯覚する要因かも。
昼過ぎ起床。
PSNサービス一部再開。アクティブなフレンドの殆どは既にログイン済みだったり(^^;
ストアはまだダメっぽい。
ftpクライアント。Webで拾ったC言語で書かれたソースをcygwinのgccでコンパイルして
(MinGWはsocket.hが無くてコンパイルできなかった為)実行してみたのですが、やっぱり
POSTを投げたところで突っかかったり。で、gdbで追いかけてみようと
した訳ですが、gdb上で実行すると何故か意図通りにリモートファイルの内容を
取得できて正常終了する罠(^^; なんだこりゃ?
なんとなくPOST 文字列の最後が"\n" になっていたのを "\r\n"
に変えたら動くようになってみたり。なんでデバッガ上から実行すると動いたのか
の方がよくわからなかったりも。
色々間違えてたりバグっぽいものにつっかかったりしましたが、やっと
ftpを経由してファイルの内容を読み取ることができたり。以下覚書き。
Webで行き当たった例は アクティブモードの方法しか見つけられなかったのですが、
パッシブモードの方がよさげだったので、そちらを使ってみました。この場合、
少しシーケンスが違ってきます。パッシブモードは大体以下のような感じ。
早くも無く遅くも無く。
ちょろり調べ事。
遅めに帰着。
特に進展無し。
遅めに帰着。
なんとなくsocketが使えるようになったので、VMWareのFTPサーバを相手に
Webで参考資料を見ながら接続の練習をしてみたり。でもなんだかうまくゆかず。
ログインはできるのですが、PORTコマンドのレスポンスが返ってこないような気が。
参考資料の一つである inetutilsに含まれるftp.cのソースを眺めてみたり。
意外と大きい(^^; なんとなく受信した文字列のパースにやたらコード量が
かかっているような気がしたりも。
遅めに帰着。
そもそもの問題は、「gdc ftptest.d -lws2_32」みたいにしても、
ws2_32.dll内の関数とリンクできないというものでした。
でも、次のようにしてなんとなく回避できる感じに。
$ gdc ftptest.d c:/WINDOWS/system32/ws2_32.dll Warning: resolving _getsockopt@20 by linking to _getsockopt Use --enable-stdcall-fixup to disable these warnings Use --disable-stdcall-fixup to disable these fixups Warning: resolving _recvfrom@24 by linking to _recvfrom Warning: resolving _recv@16 by linking to _recv Warning: resolving _sendto@24 by linking to _sendto : :省略メッセージどおりにリンカオプションを「gdc -Xlinker --enable-stdcall-fixup ftptest.d c:/WINDOWS/system32/ws2_32.dll」 てな感じで指定すると、黙ってリンクを解決するようです。
遅めに帰着。
先日のwinsock関連のライブラリがリンクできない件を調べたり。
何をやっても反応が無い感じ。うーむ。
昼過ぎ起床。
もそもそとコーディング。ftpを使ってネットワーク越しのファイルを参照したいと
思い、D言語でftpクライアントってどんな感じに書けばよいか調べたり。
なんだかイマイチ簡単な感じになっていなさげ。perlのftpモジュールくらいに
なってれば楽チンなのですが。あと、gdcだとstd.socket内で使用している
関数(winsock2関連の関数)がうまくリンクできなかったり。
いずれにしても地雷が満載という感じです。
早速地雷の中を通ってみることに。まずはwinsock2を使ったC言語の例をWebで
探して、WindowsAPIのラッパー
を使い、D言語に移植しながらリンクできるかを試したり。
ところが、次のようなので困ったり。
htons()という関数を使ったとき、この関数の実体がlibgphobos2内の
std/c/windows/winsock.d内と、MinGWのライブラリ libws2_32.a の両方に
存在して、multiple definition でリンカがエラーしました。
phobosの方はひとまず使わないので、arを使ってlibphobos内のwinsock.oを
削除してみたのですが、datetime.oがwinsock.oに依存しているようでundefined symbols
でエラー。datetime.oも削ってみると、更にそこらじゅうでundefined symbolsに
なったり。うーむ。
そもそも、何故WS2_32.dll 内に実装のある関数をlibphobosの中で独自に実装してるんだ?
TANEが何か勘違いしているのだろうか?..........
昼頃起床。
もそもそとコーディング。途中で謎な現象にぶつかりながらもどうにか回避。
遅めに帰着。
もそもそとコーディング。途中であまりの眠さに死亡。
遅めに帰着。
ちょろりコーディング。
遅めに帰着。
そういやEmacsでスクロールバーを使って水平スクロールする事って
できないんだっけ?と思ったり。少なくともemacs-22ベースのMeadow3
はダメっぽい予感。Cygwinパッケージのemacs-23で少し調べてみたところ、
toggle-horizontal-scroll-bar なるものが存在していたので、使えるのか?
と思って実行してみたら
「toggle-horizontal-scroll-bar: Horizontal scroll bars aren't implemented yet」
とか出てきてガッカリ。そういや、hscroll-mode の代わりには
toggle-truncate-lines を使うのが良いっぽい。
遅めに帰着。
ちょろっと調べ事をして終了。
遅めに帰着。
Webをちょっと見て終了。
AM中に起床。
調べものしたりもそもそとコーディングしたり。
ちょろり本屋に。「友達100人できるかな(5)」最終巻。流石に1人/1話で100人分という訳には
いかなかったようですが、全巻通して読後感の非常に良い作品だったと思います。
米国と欧州ではPSNが一部サービス再開したもよう。日本を含むアジア圏はファーム
ウェアは提供されるもののサービス再開はまだっぽい。
昼前起床。
ずっこけコードの調査。std/format.d内でsegfaultになっているのですが、
スタックトレースを見るとちょっとひっかかる所があったりも。
Program received signal SIGSEGV, Segmentation fault. formatArg () at ../../../libphobos/std/format.d:3239 (gdb) where #0 formatArg () at ../../../libphobos/std/format.d:3239 #1 0x0040be77 in doFormatPtr (putc=..., arguments=..., p_args=0x0) at ../../../libphobos/std/format.d:3828 #2 0x0040c0d5 in doFormat (putc=..., arguments=..., argptr=0x10bfba0 "\005") at ../../../libphobos/std/format.d:2742 #3 0x0040d1dc in bug2479format (arguments=..., argptr=0x10bfba0 "\005") at ../../../libphobos/std/string.d:2090 #4 0x0040d2a6 in format (_arguments_typeinfo=...) at ../../../libphobos/std/string.d:2140 #5 0x004020fd in proc (this=..., hwnd=0x630730, msg=15, wp=0, lp=0) at ProgressWindow.d:202 #6 0x0040233d in _WndProgressProc (hwnd=0x630730, msg=15, wp=0, lp=0) at ProgressWindow.d:243 #7 0x77cf8734 in USER32!GetDC () from /cygdrive/c/WINDOWS/system32/USER32.dll #8 0x00630730 in _Jv_RegisterClasses () #9 0x77cf8816 in USER32!GetDC () from /cygdrive/c/WINDOWS/system32/USER32.dll #10 0x00402234 in proc (this=..., hwnd=0x0, msg=0, wp=0, lp=6489904) at ProgressWindow.d:229 #11 0x00630730 in _Jv_RegisterClasses () #12 0x77d08ea0 in USER32!DefWindowProcW () from /cygdrive/c/WINDOWS/system32/USER32.dll #13 0x00000000 in ?? ()
string str ; synchronized{ str = format("%3d%%",rate) ; } TextOut(hdc, barx+barwidth/2, bary+2, cast(wchar*)(toUTF16(str)) , str.length);
遅めに帰着。
ずっこけコードの調査。そういやGCをdisableにするのを試してなかったので、
試してみたところ変わりなし。なんとなくスタックが壊れているのでは?
と思ったり。
調べ事をしてたらあまりの眠さに急速停止。
少し遅めに帰着。
--enable-tlsを足したgdcのビルドを使って、手持ちソースをコンパイルしたところ、
.tls_common というアセンブラの擬似コードをasが食ってくれなくてエラー。
.tls_commonでWebを検索してみるも、何故か驚くほど情報が少なくて対処方法が
判らず。
パッチを当てたりして結局ほぼ元のまま。ただ、先日の最小再現コードはSegfault無く動く
ようになってしまったのですが、元のコードはSegfault位置が変わってしまった為、
再度追いかけ直しかも。でも、thread.dから、std/format.d内に移った為、
もう少し調べ易くなったかも??
少し遅めに帰着。
色々調べる前にバージョンを新しくしておこうと思い、gdcの新しいのをビルドしたり。
今までのと同じconfigureオプションでビルドするのと、もう一つ --enable-tls を
付けたビルドを行ってみたり。
とりあえずエラー無く終了。で、先日のコードをコンパイルしてみると、Segfaultで
ずっこけなかったので、あれ?何か直ってた?と思ったのも束の間、最小パターン
じゃないコードではやっぱりダメだったり。
少し遅めに帰着。
最小パターンのコードを作成して確かめてみたり。
貼り付けるには少し大きいので、ここに置く⇒(ProgressWindow.d)
あと、コンパイルにはWindowsAPIの
バインディングが一式必要です。
まず、DMDでコンパイル&実行してみると大丈夫っぽい。なので、ずっこけるのは
gdc-MinGW特有の何かが影響しているものと思われます。
$ gdc -g -I. -static -mno-cygwin -mwindows -fversion=Unicode -fversion=WindowsXP -fdeprecated ProgressWindow.d $ gdb -q a.exe Reading symbols from C:\cygwin\home\tane\develop\dlang\prog_test/a.exe...done. (gdb) run Starting program: C:\cygwin\home\tane\develop\dlang\prog_test/a.exe [New Thread 5372.0x14a8] [New Thread 5372.0x17e0] [New Thread 5372.0x1284] Program received signal SIGSEGV, Segmentation fault. [Switching to Thread 5372.0x17e0] 0x004058a8 in remove (t=...) at ../../../libphobos/core/thread.d:1806 1806 t.next.prev = t.prev; (gdb) where #0 0x004058a8 in remove (t=...) at ../../../libphobos/core/thread.d:1806 #1 0x00405ca2 in thread_entryPoint (arg=0xcb5f00) at ../../../libphobos/core/thread.d:181 #2 0x77bea3b0 in msvcrt!_endthreadex () from C:\WINDOWS\system32\msvcrt.dll #3 0x7c80b729 in KERNEL32!GetModuleFileNameA () from C:\WINDOWS\system32\kernel32.dll #4 0x00000000 in ?? () (gdb) quit A debugging session is active. Inferior 1 [process 5372] will be killed. Quit anyway? (y or n) [answered Y; input not from terminal] $ ../../../dmd/dmd_2.052/windows/bin/dmd.exe -I. -version=Unicode -version=WindowsXP -d ProgressWindow.d $ ./ProgressWindow.exe run exit
少し遅めに帰着。
もそもそと調査。ちょっとパターンが掴めたようなそうでもないような。
昼頃起床。
昨日の調査結果で一点気になる所があったので調べたり。
ptrlistを静的配列ではなくて、動的配列にした場合は問題無くガベージコレクトされたという点。
これ、int配列じゃなくて本当にポインタを保持する為のポインタ配列にしてもガベージコレクト
されちゃうんだっけ?という疑問が沸いてきたり。で、
昨日のコードの33行目を「void*[] ptrlist ; ptrlist.length=1000 ;」に、
49行目を「ptrlist[i] = storage1.array.ptr ;」として、動的配列にしたポインタリスト
にポインタを保持するようなコードに書き換えてみたところ、ガベージコレクトは
されないようでした。
よく調べてませんが、本当のポインタリストにした場合は GCのrootが新たに
追加されているものと思われます。
手持ちコードのgdc 2.052対応。プログレスウインドがうまく動かず。
スレッドを使って非同期に進行をウインド表示しているのですが、
スレッド実行が終了した後、core/thread.d内で終了したスレッドをリストから
外す所で何やらSegfaultになっていたり。gdbでずっこける手前で止めて、
スレッドリストを表示してみると、リストの中身が壊れている為かいきなりgdbが死んだりして
どうにも調べが付けられず。
なんとなく スレッドの中でCreateWindowEx()を実行すると何故かスレッドリストが
壊れる予感。
昼頃起床。
DMDの方でGCに関するバグ報告が挙がってないだろうか?と思い、
digitalmars.D.bugs
を探してみたり。ひとまず「GC」という文字列でタイトル一覧を文字列検索したところ、
例えばこんなの(GC.collect() and GC.minimize() not releasing memory)
が見つかったり。でも、勘で読み進めているとこの掲示板は正式にバグ報告をする場
では無いようで、Bugzillaでバグレポートは管理されている模様。で、
何か見解が得られているのか見てみようとする訳ですがアカウントが必要らしい。
えー?面倒臭いなぁ?
てか、Web検索エンジンとかでも引っ掛けられるように見るのだけはアカウント
無しにして欲しいんですけど。
そんな訳でBugzillaのアカウントを取得して眺めてみる訳ですが、英語がダメな
TANEには投稿数が多すぎて読みきれません(^^;;; ただ、上に挙げた掲示板で見つけた
報告はBugzillaには登録されていない模様。もし再現すれば今回TANEが調べたのと同じ原因に
到達できると思われる核心をついたコードだと思うのですが。
DMDでも再現するようなGCにコレクトされない例を作ってみました。
$ cat -n gc_test.d 1 // 2 // メモリ割り当ての挙動を見る 3 // 4 import std.stdio ; 5 import std.string ; 6 import core.memory ; 7 import std.conv; 8 9 class Storage{ 10 private byte[] array ; 11 static int no_master ; 12 int no ; 13 14 this(int size){ 15 no=no_master ; 16 no_master++ ; 17 writef("construct! no=%d\n",no) ; 18 array.length = size ; 19 } 20 21 ~this(){ 22 array.length=0 ; 23 //delete array ; //(1)コレが入っているとガベージコレクトされる 24 writef("destruct! no=%d\n",no) ; 25 } 26 } 27 28 int main(string args[]) 29 { 30 Storage storage1 ; 31 int alsize ; 32 int loopnum ; 33 int[1000] ptrlist ; 34 35 if( args.length == 3 ){ 36 alsize = to!(int)(args[1]) ; 37 loopnum = to!(int)(args[2]) ; 38 loopnum = loopnum>1000 ? 1000 : loopnum<=0 ? 1 : loopnum ; 39 }else{ 40 writef("args memsize[MB] loop\n") ; 41 return(0) ; 42 } 43 core.memory.GC.collect() ; 44 45 writef("===loop start===============================================================\n") ; 46 for( int i=0 ; i<loopnum ; i++ ){ 47 int size=1024*1024* alsize ; 48 storage1 = new Storage(size) ; 49 ptrlist[i] = cast(int)(storage1.array.ptr) ; 50 writef("**********array_ptr=%08x\n",storage1.array.ptr) ; 51 core.memory.GC.collect() ; 52 } 53 writef("===loop end=================================================================\n") ; 54 55 return(0) ; 56 } 57 $ ../dmd/dmd_2.052/windows/bin/dmd.exe -O gc_test.d $ ./gc_test.exe 1 500 ===loop start=============================================================== construct! no=0 **********array_ptr=00b10010 construct! no=1 :省略 **********array_ptr=23e50010 destruct! no=497 construct! no=499 **********array_ptr=23f51010 destruct! no=498 ===loop end================================================================= destruct! no=499
早くも無く遅くも無く。
GCでのメモリ割り当てには、gdc-MinGWでは WinAPIであるところの
VirtualAlloc()を使用しています。VirtualAllocのフラグに
MEM_TOP_DOWNというのがあり、これを使用するとできるだけ上位のアドレス
でメモリを割り当てるという事なので試してみたり。
実際には上位のアドレスといっても0x80000000よりは小さいアドレスで
割り当てられるようですがひとまずいけるかな?という感じ。でも、
あまり芳しくない結果になったり。よく見れてませんが
ポインタリストの中には何やら残骸的な物も含まれていて、それらに
ヒットしてしまう感じがしたりも。どういう時にスタックに積まれる
場合があるのかは判りませんが、例えばコンパイル時の最適化レベルを
変えたりすると、うまく動いたり(または動かなくなったり)する場合が
あるのでは?とも思ったり。うーむ。
オリジナルのDMDでは巨大動的配列のガベージコレクトは
大丈夫だった訳ですが、
GCのコードはgdcと基本的な部分は同じです。一体この問題をDMDの方では
どうやって回避している事になるんだろう?
あまりの眠さに急速停止。
昼頃起床。
GC調査。ぼんやりソースを眺めていたところ、なんとなく流れがつかめたような
そうでもないような。
core/thread.dというソースの中にthread_scanAll()という関数があり、この中で
メモリ領域をスキャンして使用中か否かをマークしているというのは昨日までの感じ。
で、thread_scanAll()内では、スキャンする領域がWindowsがプラットフォームの場合は
3種類あるようです。
一つ目はスタック領域(これは全スレッドで共通?)、二つ目は各スレッド毎の
TLS領域、三つ目は各スレッド毎のレジスタ退避領域(っぽいもの)。Windows以外では
三つ目の領域退避は不要なようです。で、何故か使用中マークが付けられるのは
一つ目のスタック領域のスキャン結果という事が判ってみたり。
Linuxのと動きを比べながら調べていたのですが、何故か全然違う動きになってしまってて、
比較がうまくできなかったり。
んー、なんとなく徐々に判ってきたような気がするようなそうでもないような。
まず、gcx.d内 Gcx.mark(void *pbot, void *ptop)の動きから。ptop〜pbotの範囲を
ポインタリストとみなして、リストの各要素がもしメモリプールの中を指している
ならば、そのアドレスは有効として使用中にマークするという
動作を行っているようです。ちょっとひっかかるのは、このポインタリストはメモリ
アドレスを指していない値がが含まれている点です。実際の例を挙げてみます。
例えば、動的配列を割り当てるとメモリ上は「配列サイズ,実メモリへのポインタ」
の並びになっています。
(gdb) print/x &strage1.array $5 = 0xcc4ca8 (gdb) print/x 0xcc4ca8 $6 = 0xcc4ca8 (gdb) x/4x 0xcc4ca8 0xcc4ca8: 0x03200000 0x01400010 0x00000000 0x00000000 ~~~~~サイズ ~~~~~ポインタ (gdb) print/x strage1.array.ptr $7 = 0x1400010
0x22fc64: 0x00000008 0x0022fce8 0x004015f5 0x00cc4c80 ~~~~~~~~~~ 0x22fc74: 0x03200000 0x01400010 0x00000063 0x00cc1e00 ~~~~~~~~~~~~~~~~~~~~~~~~~~
(gdb) print/x &strage1.array $10 = 0xcc4c88 (gdb) x/4x 0xcc4c88 0xcc4c88: 0x03200000 0x05f20010 0x00000001 0x00000000 (gdb) print/x strage1.array.ptr $11 = 0x5f20010
0x22fc64: 0x00000008 0x0022fce8 0x004015f5 0x00cc4c60 ~~~~~~~~~~ 0x22fc74: 0x03200000 0x05f20010 0x00000063 0x00cc1e00 ~~~~~~~~~~~~~~~~~~~~~~~~~~
(gdb) print/x this.minAddr $17 = 0xcc0000 (gdb) print/x this.maxAddr $18 = 0xaa38000
昼前起床。
GC調査。Linuxの方でgc/gcx.dを調べたり。コンパイルオプションに -fdebug=COLLECT_PRINTF
指定して、元々仕込まれているコレクトに関するデバッグプリントを活かしてみたところ、
fullcollectで領域開放されていることが判ったり。つまり、何かの閾値がある訳ではなく、
単純にコレクトが効いているから、メモリ割り当て量×2くらいで使用量の最大が自然に
決まっているという感じのようです。
一方 MinGW-gdcの方で同じようにデバッグプリントを見てみたところ、fullcollectは
実行されているものの、ちっともメモリを開放していないようです。
なぜコレクトが効いていないのかが謎。プラットフォーム依存のコードは通っていないように
思えるんだけどなぁ?
LinuxとMinGWとを比べながら動作を追いかけてみたり。gcx.d内でpool.mark.test()なる
関数で空きページか否かを判定して、空きページであればメモリを開放するという動作
を行っているようなのですが、MinGWでは何故かマークのテストがいつも使用中を返して
しまう為、メモリ開放コードを通らないという動きになっていたり。その使用中マークをどこで
付けているのか追いかけてみるとthread_scanAll()なる関数で行われていたり。
むぅ、またthread関連ですか?少し追いかけてみるもどこでセットされているか良くわからず。
ちょっとずつブレークポイント位置を変えながら値の変わる前後を絞りつつ、最後はwatchポイントを
設定してみたところ、なんとか触っているコードに辿り着いたり。
(gdb) watch *(int*)(0xc10024)!=0 Hardware watchpoint 8: *(int*)(0xc10024)!=0 (gdb) c Continuing. Hardware watchpoint 8: *(int*)(0xc10024)!=0 Old value = 0 New value = 1 0x0043adba in testSet (this=..., i=0) at ../../../libphobos/gc/gcbits.d:178 (gdb) where #0 0x0043adba in testSet (this=..., i=0) at ../../../libphobos/gc/gcbits.d:178 #1 0x00436620 in mark (this=..., pbot=0x22f974, ptop=0x230000) at ../../../libphobos/gc/gcx.d:2259 #2 0x0041a561 in thread_scanAll (scan=..., curStackTop=0x22f974) at ../../../libphobos/core/thread.d:2583 #3 0x00436a58 in fullcollect (this=..., stackTop=0x22f974) at ../../../libphobos/gc/gcx.d:2418 #4 0x00436755 in fullcollectshell (this=...) at ../../../libphobos/gc/gcx.d:2326 #5 0x00435d17 in bigAlloc (this=..., size=52428817, alloc_size=0x22fb98) at ../../../libphobos/gc/gcx.d:2024 #6 0x0043125e in mallocNoSync (this=..., size=52428817, bits=10, alloc_size=0x22fb98) at ../../../libphobos/gc/gcx.d:500 #7 0x00430de4 in malloc (this=..., size=52428817, bits=10, alloc_size=0x22fb98) at ../../../libphobos/gc/gcx.d:414 #8 0x0041b484 in gc_qalloc (sz=52428817, ba=10) at ../../../libphobos/gc/gc.d:207 #9 0x0040c216 in _d_arraysetlengthT (ti=..., newlength=52428800, p=0xcc4c88) at ../../../libphobos/rt/lifetime.d:1326 #10 0x004013bf in __ctor (this=..., size=52428800) at mem_test2.d:18 #11 0x004015f2 in main (args=...) at mem_test2.d:51 #12 0x0040d4eb in runMain () at ../../../libphobos/rt/dmain2.d:529 #13 0x0040d54e in tryExec (dg=...) at ../../../libphobos/rt/dmain2.d:480 #14 0x0040d658 in runAll () at ../../../libphobos/rt/dmain2.d:544 #15 0x0040d54e in tryExec (dg=...) at ../../../libphobos/rt/dmain2.d:480 #16 0x0040dcf8 in _d_run_main (argc=3, argv=0x3e2c70, main_func=0x401474 <main>) at ../../../libphobos/rt/dmain2.d:554 #17 0x00401944 in main (argc=3, argv=0x3e2c70) at ../../../libphobos/rt/cmain.d:5 (gdb)
昼頃起床。
まも呪。ボチボチ。ちっとも上達しない気が。
そういやInkscapeのSVGパーサーってどう書かれているんだろう?と思い、
ソースを眺めてみたり。んー?なんだかコードジェネレータ的な物を使って
ないような気が....?手書きなのかしら?
もそもそとコーディング。途中GCのバグと思われるものが発動したりして
困ったり。そういや、以前Phobosの
GCがイマイチで、それが2.052対応のgdcだとどうなってるかを
再度確認した時、あまり変わってないなぁ
と思った訳ですが、dmdのオリジナルでは確かめた事が無かったなぁと思ったり。
で、試した訳ですがどうやらdeleteで明示的に動的配列を開放しなくても
OOMにはならない模様。
また、確認環境が無かった Linux(on VMWare)の方でも2.052対応のgdcで
確認した所、こちらもOOMにはなりませんでした。ただし、明示的にdeleteを
入れた方がヒープの広がり具合は小さいので、チューニングのために使うのはアリっぽい。
そんな訳で、動的配列を明示的にdeleteしないとOOMになるのは MinGWのgdc特有の問題だったっぽい。
なんとなくGCを調べたり。OOMになるのは phobos特有の話だと思っていたのですが、
MinGWのgdc限定となると話は別です。Linuxでメモリの具合をモニターを使って
見ていたところ、適当なサイズを上限に再利用が効いている感じでした。
DMDのオリジナルでもプロセスサイズの上限に達するよりも大分前に再利用が
効いている感じでした。そもそも一体何を再利用発動の閾値としているのだろうか?
と思ったり。GCの本体コードであるgc/gcx.dはプラットフォームの違いによるコード
切り替えは無いようなのにも関わらず、何故このように動きに違いが出るのかが
よく判りません。
少しデバッガで動きを眺めてみたところ、gcx.bigAlloc()が失敗しているようなの
ですが、何故だかブレークポイントがうまく設定できなくて、失敗が確定するまでの
経路を特定できなかったり。むー。
早くも無く遅くも無く。
まも呪。昨日は全然ダメだったステージも、一発目ならうまくいく不思議。でも続けてやると
だんだん伸びなくなる罠。
眠くて死亡。
昼過ぎ起床。
まも呪をボチボチ。集中力が切れると連続死する為伸びず。
PSN不正アクセスのその後。何やらFBIに調査依頼したとか大事になっている気も。
まぁでも、これだけ大規模なサービス停止となると、損失は莫大なものになると
想像されます。もし犯人が居るのであればここはしっかり捕まえて、
誰も得をしないという事を知らしめて欲しい所なのかも。