Muse掲示板

使い方 新規投稿 新着記事 ツリー表示 ワード検索 過去ログ 管理モード

過去ログ表示

過去ログ3 を表示

表示ログ 過去ログ1 過去ログ2 過去ログ3 過去ログ4
過去ログ5 過去ログ6

過去ログ検索は 検索 より行えます。
記事数 / 1302件 (401-420 を表示) / 全ページ数 / [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16] [17] [18] [19] [20] [21] [22] [23] [24] [25] [26] [27] [28] [29] [30] [31] [32] [33] [34] [35] [36] [37] [38] [39] [40] [41] [42] [43] [44] [45] [46] [47] [48] [49] [50] [51] [52] [53] [54] [55] [56] [57] [58] [59] [60] [61] [62] [63] [64] [65]

No.8479/Re[15]: NO TITLE
■投稿者/ himajin925 -(2012/11/20(Tue) 21:18:45)

    どうも、こんばんは

    逆に JJさんの「シバの女王ベルキス」から、事前に無名マクロを展開・削除した mus ファイルを作り(有名マクロはそのまま)、Ver6.26 にかけたところ、現象はおきないようでした。
    すると開発者さん、Elekenさんが言われるように、無名マクロの評価の辺りに?があるのでしょうか
    >>JJさん、いろいろいじってすいません。コピーしたものでやってます

    もうひとつ、
    Ver6.26a(a なしも同様のようです)で、第2曲の直前(同じ場所)で右クリック、再ロードさせて、 WM_SETTEXT の様子を Spy で見ていると、一回ずつ第1曲のメッセージのアドレスが(比較的)低位アドレス←→高位アドレスと交互に変わるようでした。前回のコンパイルが再ロードに影響している?のでしょうか
    (すぐ後続する第2曲のメッセージのアドレスは毎回同じ)
    関係なさそうであれば、後で教えてください

    ***追記
    無名マクロをすべて有名マクロ(その場で定義、参照)に置き換えたところ、Ver6.26 で「2.戦いの…」が表示されない現象がおきました。無名マクロだけとは断定できないようです。それともこういう場合は、無名マクロと同じ扱いでしょうか?

    (無名マクロを、あらかじめ展開したもの、有名マクロで置き換えたもの、両方エクスポートするとオリジナルと同じ midi ファイルが出力されます)
記事No.8422 のレス / 関連記事表示
削除チェック/

No.8483/Re[16]: NO TITLE
■投稿者/ 開発者 -(2012/11/23(Fri) 02:28:02)

    himajin925さん
    > 無名マクロをすべて有名マクロ(その場で定義、参照)に置き換えたところ、Ver6.26 で「2.戦いの…」が表示されない現象がおきました。無名マクロだけとは断定できないようです。
    実験およびその結果情報を、ありがとうございます。
    有名マクロは、ユニークなマクロ名を与えなければならないので、
    さぞや大変な作業だったのではないかとお察しします。
    私も一時やってみようと思ったのですが、
    あまりに面倒だったので諦めてしまっていました。
    本当にありがとうございました。

    > それともこういう場合は、無名マクロと同じ扱いでしょうか?
    定義部分の扱いが微妙に異なりますが、展開部分を同一に扱えるように工夫しています。
    今までの実験からすると、ロード時のコンパイル処理において、
    メモリの確保と解放が激しく、そして大きく実施される場合に、
    症状が出るような気がしています。
    もしかしたら、マクロに因らないのかもしれません。

    free()に不正なアドレスを送信して、メモリ破壊をしているかもしれないと考え、
    症状が出現する際のmalloc()とfree()のアドレスを全ダンプし、整合確認をしてみました。
    結果は、すべて正常でした。

    以下、経過報告です。
    ------------
    再現性が高く、極めてシンプルなデータ[8475]は確保できましたが、
    Museの内部データの破壊箇所が見つからないため、
    破壊箇所から問題を推論していくというアプローチを断念し、
    再現するプログラムと再現しないプログラムの差を詰めて行くという
    コーディングからのアプローチに方針を変えて、先日よりトライしていました。

    [8475]のデータで改めて実験し直すと、
    V5.70β2とβ3の間で、明確な再現の境界が見出されました。
    β2以前では再現せず、β3以降では再現します。
    そこで、β3のプログラムに慎重に手を加え、症状を残したまま次第にβ2に戻していく作業を試みました。

    そして、なんと最後は差異が1行になったのです!
    で、その結果に愕然としました。

    実は私自身もすっかり忘れていたのですが、
    β2は、文字列の先頭に1バイト加えて、そこに文字区分(TEXT/MARK/STOP)を与えていたのです。
    そして、表示する際は2バイト目以降をSetTextWindowに送っていました。
    一方β3では、演奏時の効率を高めるために、文字区分は別の構造体のフラグに担わせ、
    送信する文字列メモリは、きっちり文字列と同じ長さを確保するようにしていました。

    上記の「1行の差異」は、そのメモリ確保の行です。
    つまりなんたる偶然かβ2とβ3の差異は、まさにメモリ確保量の差であり、
    今回の対処療法と同じヒントしか得られなかったという顛末です。

    そこで思い立ちました。
    Museが内部で1バイト足しているならば、
    もしかしたらV5.7β2以前のバージョンは、
    1文字少ない29文字のMARK文を指定したら症状が出るかもしれない。
    そう思って実施したところ、まさに予想的中。症状が出ました!

    一体、どこまで遡れば症状が出なくなるのだろう・・・。
    やってみました。
    途中からMARK文をサポートする以前のバージョンに突入したので、
    TEXTに切り換えて実験しました。TEXTでも症状が出ます。
    そして、とうとうV3.1にまで到達してしまいました。

    実は、ソースが現存するのはここまでなのです。
    ソースがなければVS2005でビルドし直せません。
    そして、再現するバージョンと再現しないバージョンのプログラムコードを
    比較して調査するという手段も断ち切られました。

    次なる手立ては、V3.1のプログラムを症状を残したまま削り取っていき、
    真因を探り当てることです。いわば、プログラムの純正培養。
    現在、すべてのダイアログは消し去られ、
    MIDI音源へのデータ転送(つまり演奏機能)も失ったMuseになっています。
    文法も、音符とマクロ位しかコンパイルできません。
    それでもなお、[8475]のデータで症状が出ています。
    このままいくと、Muse が Hellow World! みたいになっちゃうかも(笑)。
記事No.8422 のレス / 関連記事表示
削除チェック/

No.8484/Re[17]: NO TITLE
■投稿者/ Eleken -(2012/11/23(Fri) 03:26:09)

    デバッグ大変お疲れ様です。

    少し前の書き込みに関してですが、
    > なんと面妖なことに、Spy++でメッセージが送られていない状況でも、
    > ・戻り値は、TRUE
    > ・文字列は正常な30文字
    > が確認されました。

    ということは、あまり考えにくいですが、この部分で別のウィンドウハンドルが指定されているかもと思いました。
    (実験したところ、別プロセスのウィンドウへ SetWindowText を送ると、
     Spy++ に WM_SETTEXT がキャプチャされないで、関数は TRUE を返すようです。)
    試しに、この部分を
    SendMessage(hWnd, WM_SETTEXT, 0x00, (LPARAM)text);
    に置き換えると、(hWnd が有効ならば)Spy++ にメッセージが反映されるのではないかと思います。無効なウィンドウハンドルならば FALSE が返るはずです。

    あと、ヒントになるかわかりませんが、失礼ながら実行時の Muse(ver.6.26) をメモリダンプして解析したところ、次のことが分かりました。
    ・メモリ上に確保された MARK 文のテキストの最初の文字 (半角スペース) から見て、オフセット -3 バイト目のメモリが、
     ・正常に表示されるテキスト -> 0x01
     ・表示されないテキスト -> 0x11
     になっている
    このアドレスのメモリが何を表すのか分かりませんし、他の環境でどうなるかもわかりませんが、この共通点は少し怪しそうです。


    ところで、別件のバグの件ですが、MuseWiki にある対処法では、例えば
    #A0| {d4r @Y0 mf}4
    #A1| {@Y1 _1}4
    のデータにおいて、#A0 の Y0 は最初の1回しか発行されない気がします・・・。
記事No.8422 のレス / 関連記事表示
削除チェック/

No.8485/Re[18]: NO TITLE
■投稿者/ 開発者 -(2012/11/23(Fri) 11:08:32)

    Elekenさん
    高度な解析による数々のご助言、痛み入ります。
    そして、強い尊敬の念を禁じ得ません。

    > デバッグ大変お疲れ様です。
    大変ではありますが、しかしこうして
    Elekenさんをはじめ、一緒に闘ってくれる同志がいるので、
    なんだかこの“戦いの踊り”自体が楽しくなってきました。(笑)

    > ということは、あまり考えにくいですが、この部分で別のウィンドウハンドルが指定されているかもと思いました。
    > (実験したところ、別プロセスのウィンドウへ SetWindowText を送ると、
    >  Spy++ に WM_SETTEXT がキャプチャされないで、関数は TRUE を返すようです。)

    > 試しに、この部分を
    > SendMessage(hWnd, WM_SETTEXT, 0x00, (LPARAM)text);
    > に置き換えると、(hWnd が有効ならば)Spy++ にメッセージが反映されるのではないかと思います。
    こちらが状況を正確にお伝えしていなかった事をお許し頂きたいのですが、
    実は、現在のMuseはSetTextWindow()を一切使っておらず、
    それが必要なところはすべからく SendMessage(hWnd, WM_SETTEXT, 0x00, (LPARAM)text) を発行しています。
    (一年以上前、Αφροδιτηさんと“文字列表示による演奏のもたつき”に対応した際、
     本ポリシーの採用が有効であると判断しました)

    というわけで、今までのメールでSetWindowText()の戻り値をご報告した際は、
    その部分をSetWindowText()に変更して実験し、その結果をお伝えしていました。

    で、今度はSendMessage()そのものの戻り値を確認してみました。
    すると、正常な時の戻り値は1、症状が出る時の戻り値は0でした!
    (何故、SetWindowText()に書き換えると戻り値が共に1になってしまうのかは謎ですが・・・)

    早速、GetLastError()を発行してみました。
    しかし、こちらの戻り値は、症状が出る/出ないに限らず0x00000000 でしたorz。

    実は私は、GetLastError()を利用した経験がありません。
    以下の様なコードを組んだのですが、これで正しいでしょうか?

    --------------------------------------------------------------
    DWORD kato;

     ・
     ・
     ・

    SendMessage(hWnd, WM_SETTEXT, 0x00, (LPARAM)text);
    kato = GetLastError();

    <ここでkatoの値を確認>

     ・
     ・
     ・
    --------------------------------------------------------------

    なお、第一引数で指定しているウィンドウハンドル(hWnd)の内容も確認しました。
    こちらは、症状が出る/出ないに限らず同一のアドレスだったので、異常は無いと思います。

    > あと、ヒントになるかわかりませんが、失礼ながら実行時の Muse(ver.6.26) をメモリダンプして解析したところ、
    いゃ〜ん。Elekennさん、エッチィ〜!(笑)

    > ・メモリ上に確保された MARK 文のテキストの最初の文字 (半角スペース) から見て、オフセット -3 バイト目のメモリが、
    >  ・正常に表示されるテキスト -> 0x01
    >  ・表示されないテキスト -> 0x11
    >  になっている
    > このアドレスのメモリが何を表すのか分かりませんし、他の環境でどうなるかもわかりませんが、
    > この共通点は少し怪しそうです。
    これは実に ぁゃιぃ ですね。
    でも、“オフセット -3 バイト目のメモリ”となると、アプリケーション側からは制御不能ですねぇ〜。
    せめて、メモリの後方であれば何か探りを入れることができたのですが・・・。

    > ところで、別件のバグの件ですが、MuseWiki にある対処法では、例えば
    > #A0| {d4r @Y0 mf}4
    > #A1| {@Y1 _1}4
    > のデータにおいて、#A0 の Y0 は最初の1回しか発行されない気がします・・・。
    流石、Elekenさんですね!
    実は、私もあの後すぐに気づいて他の方法で対応済みです。
    MuseWikiの更新を怠っていました。申し訳ありません。
記事No.8422 のレス / 関連記事表示
削除チェック/

No.8487/Re[19]: NO TITLE
■投稿者/ himajin925 -(2012/11/23(Fri) 16:18:29)

    どんどん削っていったソースは、そのままで VC++6 でコンパイルできますか?
    VC++6 でそのままのソースで OK となったりしたら…

    SendMessage が何を返すかは、呼び出すコントロールによると思うので、きっと GetLastError でもエラーは拾えないと思われます。
    STATIC コントロールが 0 を返す条件は分かりませんでした。やはり Message が飛んでいない(STATIC に制御が渡っていない)のでしょう。不正なアドレスを渡すと飛ばなかったりしますが、SetWindowText 内で try 節などで保護されているのでしょうか。それともそれ以外の条件か…

    VC++ 2005 Express Edition って言うのを拾ってきましたが、お使いなのはこのエディションでしょうか?まだインストールを、躊躇してます(^_^;)
記事No.8422 のレス / 関連記事表示
削除チェック/

No.8488/Re[20]: NO TITLE
■投稿者/ 開発者 -(2012/11/23(Fri) 18:57:35)

    > どんどん削っていったソースは、そのままで VC++6 でコンパイルできますか?
    はい、できます。
    現時点での、純正培養Museをアップしておきました。
    http://www1.c3-net.ne.jp/kato/data/muse.zip

    起動すると即、添付のtest.musというファイル限定でロードします。
    許される文法は、TEXTとドと休符と無名マクロのみです。
    音長指定さえできません。
    GUIとしては、メニューも鍵盤もありません。もちろん各種ダイアログも無しです。
    アイコンすらありません。

    起動後、上矢印キー[↑]の押下で、リロードし曲頭からの再生をします。
    再生しますが、音は出ません。(笑)

    正常な動作は、
     (1)テキストエリアに HEAD という文字列が表示される
       (これはデバッグ用にプログラムが表示しています。色は黒です)
     (2)白い鍵盤が1つだけ表示される
     (3)テキストエリアに 1234・・・の30文字が表示される
       (これはデータtest.musから読み取っていますが、色は黒です)
     (4)鍵盤が赤くなる(ここで本来の演奏開始です)

    しかし何度か[↑]を押下してリロードを繰り返すと、上記の(3)が実行されずに、
    テキストエリアに HEAD が表示されたまま、鍵盤が赤くなります。
    これがまさに今回の症状です。

    今のところ、純正培養Museはここまで来ています。
    サイズは100Kもありません。
    ソースも24Kしかないので、皆さんのMuseデータより小さいかも(笑)。
    これから、無名マクロの処理に手を入れていこうと思います。

    > SendMessage が何を返すかは、呼び出すコントロールによると思うので、
    > きっと GetLastError でもエラーは拾えないと思われます。
    ご教示ありがとうございます!
    でも、何らかの糸口がつかめるかと思ってたので、残念です。

    > 不正なアドレスを渡すと飛ばなかったりしますが、SetWindowText 内で try 節などで保護されているのでしょうか。
    いいえ、try文は一切使っていません。

    > VC++ 2005 Express Edition って言うのを拾ってきましたが、お使いなのはこのエディションでしょうか?
    はい。そうです。
    ただし、MuseはVC++ではなく、Cで開発しています。
    また、実はVisual Studioさえ使っていません。
    テキストエディタでコーディングし、コマンドプロンプトでコンパイルしてます。
記事No.8422 のレス / 関連記事表示
削除チェック/

No.8489/Re[21]: NO TITLE
■投稿者/ himajin925 -(2012/11/24(Sat) 00:16:32)

    SendMessage (SETTEXT) で送るメッセージが HEAP の末尾に来た場合、メッセージが飛んでいないようです。なぜそうなるのでしょう?
    Win95、98、Me ではおきず、XP 2000 でおきるというと、 SendMessage の変換 (UNICODE 関連)のあたりの仕様の違いに関連ありそうとは思いましたが、これはという情報はまだ見つかってません。

    症状が一定しないのは、きっと単なるリロードでは HeapCreate しなおしていない?のではないか、と思いました。前のコンパイルの HeapAlloc したメモリが残っている、などないでしょうか?

    32バイトちょうどだとなぜ末尾に来るのか?(もしかすると、このメッセージの分を HeapAlloc する際、拡張が起きているのかな?)
    なぜ末尾ではいけないのか?←これが問題ですね。まだまだ分かりません。

    ただ、どうも「アプリのバグ」という感じではない、と思います

    多分 私の環境でも、release ビルドだったら、HeapAlloc したときの保護バイトが付かないだろうから(?)、Heap の最後に確保されるように工夫して、SendMessage してみようと思います。
記事No.8422 のレス / 関連記事表示
削除チェック/

No.8490/Re[22]: NO TITLE
■投稿者/ 開発者 -(2012/11/24(Sat) 02:02:12)

    > Win95、98、Me ではおきず、XP 2000 でおきるというと、 SendMessage の変換 (UNICODE 関連)のあたりの仕様の違いに関連ありそうとは思いましたが、これはという情報はまだ見つかってません。
    私のパソコンはWin7ですが、Win7でも症状は出ていません。
    なにか、考察のヒントになるでしょうか?

    > 症状が一定しないのは、きっと単なるリロードでは HeapCreate しなおしていない?のではないか、と思いました。前のコンパイルの HeapAlloc したメモリが残っている、などないでしょうか?
    何か確認する方法がありましたら、ヒントでも頂けると助かります。
記事No.8422 のレス / 関連記事表示
削除チェック/

No.8492/Re[23]: NO TITLE
■投稿者/ himajin925 -(2012/11/24(Sat) 09:00:11)

    開発者さん、Elekenさん、皆さん、おはようございます。
    (1)HeapCreate はプログラムから明に呼び出しているのでしょうか?それとも VS のライブラリから(勝手に、というか)呼び出されているのでしょうか?後者だとすると、方法は(まだ)分かりません→メモリリークというわけではないので、重要ではないと思います

    (2)もう一つやってみていただきたい事があるのですが、プログラムの先頭のあたりで setlocale(LC_ALL, "Japanese"); を指定すると、どうでしょう?変化ないかな

    ではまた調べます
記事No.8422 のレス / 関連記事表示
削除チェック/

No.8493/Re[24]: NO TITLE
■投稿者/ 開発者 -(2012/11/24(Sat) 11:09:57)

    ●himajin925さん
    お知恵を頂き、ありがとうございます!

    >(1)HeapCreate はプログラムから明に呼び出しているのでしょうか?それとも VS のライブラリから(勝手に、というか)呼び出されているのでしょうか?
    後者です。
    Museプログラム上では、HeapCreateを発行していません。
    ただ、Museが発行したmallocから、HeapAllocが利用されていると思います。

    余談ではありますが、
    Muse(V6.20)開発の折、データロード速度が低下したのをきっかけにいろいろ調べました。

    例えば、
    http://www7a.biglobe.ne.jp/~tsuneoka/win32sub2/10.html
    # Cランタイムルーチンの関数は、
    # OSの内部構造を理解していない開発者が Win32 API を利用して作成したものよりは
    # 機能、性能共に優れていることがほとんどです。
    # 実際にmalloc関数 と 代表的なメモリ管理APIを利用したベンチマークテストを実行してみると分かります。
    # 2048バイトのメモリの取得・解放を10万回ループさせてみると、
    # malloc と、 Win32 API LocalAlloc, GlobalAlloc では、処理速度の差が20倍程度ありました。

    http://ir9.jp/prog/ayu/datlog/tech_win32api/1006783012/1006783012_03.html
    # 542 名前:511 :02/02/02 10:55
    # 実際やってみました。いろいろ適当なプログラムですが
    # ・・・
    # 結局malloc()よりHeapAlloc()の方が約1.9倍遅かったです。

    他にも同じ傾向の主張をしているサイトが多かったため、
    プログラム全域に渡ってCランタイムを中心とするコーディングに改修しました。
    当初は、この改修が災いしたのかとも思いましたが、
    過去のMuse(V3.1)まで遡っても症状が出るので、因果関係は薄いと見ています。


    >(2)もう一つやってみていただきたい事があるのですが、プログラムの先頭のあたりで setlocale(LC_ALL, "Japanese"); を指定すると、どうでしょう?
    V6.26で(V6.26aではない)試してみました。
    結果は、変化無しでした。

    また、純正培養Museでも試してみました。
    これも結果は、変化無しでした。


    ●Elekenさん
    > カーネルのバグで、NULL 終端を越えて走査しようとしてしまう・・・
    もしそうだとすると、[8458]で浅川さんがつぶやいた、
    > むしろこの場合XPのOS側にバグがあると考えたほうが自然かもしれません。
    ということなのかもしれませんね。

    > この NULL 終端がヒープ末尾に来る文字列の問題は、以下の簡単なプログラムで確認できます。
    素晴らしい!
    これこそ、純正培養アプリケーションですね。

    > HeapAlloc を呼び出した時点の残り割り当て可能領域に依存します。
    思い当たる節があります。
    純正培養Museを作る過程で、本来必要なFree()部分をコメントアウトしたら、症状が出なくなりました。
    また、機能を削り取ることで不要となった構造体のメンバをコメントアウトしたら、症状が出なくなったこともありました。

    > こちらの環境 (WinXP, コンパイラ VC++6.0) では、少なくとも
    > (ヒープ領域サイズ, 割り当てサイズ) = (16384, 32), (16384, 24), (8192, 24), (8192, 16) のときに発生します。
    つまり、VS2005でのビルドは条件ではなかった!
    ついに真因を突き止めたような感じですね。

    どこかのサイトに、有効な回避手段が掲載されていないかなぁ〜。
記事No.8422 のレス / 関連記事表示
削除チェック/

No.8494/Re[25]: NO TITLE
■投稿者/ himajin925 -(2012/11/24(Sat) 13:07:45)
□U R L/http://blog.livedoor.jp/sage_p/archives/50914558.html

    先ほどまでの報告に訂正があります。Elekenさんの先ほどの実験を確かめていただきたいのですが、
    純粋培養 Museにおいて、
    バッファが Heap の末尾に Alloc されたに場合、文字列の最後に NULL がないのかもしれません。デバッガでダンプを見ていたのですが、「先頭アドレスから 4バイト幅、16バイト幅で表示」すると OK (NULL があるように見える)なのですが、開始アドレスを +1 したり、表示幅を変えてみてみると、31バイト目の '0'(=0x30) の次からが ?? と表示されます。(32バイト目を含み、それ以降)

    開発者さんの環境では AfxIsValidString などは呼べるのでしょうか?呼べるようであれば SendMessage の前後で呼んでみてくれませんか。(または相当する関数)また _msize などによって、割り当てられたバイト数を確認する、なども出来ますか?
    Elekenさんの実験でも、ラストのメモリブロック、末尾の NULL が格納されているか、ダンプ幅を変えて見るなどして確認してみてくれませんか?

    ただ、ダンプのバグだって考えられますが、一応確認お願いします

    **
    ↓malloc のバグだ、という人もいますが…判断できません
記事No.8422 のレス / 関連記事表示
削除チェック/

No.8495/Re[26]: NO TITLE
■投稿者/ Eleken -(2012/11/24(Sat) 17:36:47)
□U R L/http://blog.livedoor.jp/sage_p/archives/50914558.html

    > Elekenさんの実験でも、ラストのメモリブロック、末尾の NULL が格納されているか、ダンプ幅を変えて見るなどして確認してみてくれませんか?
    VC++6.0 と userdump 両方で確認しましたが、NULL 終端は格納されているようです。
    ちなみに、ユーザ側プロセスからヒープ末尾(NULL 終端)以降をアクセスしようとすると、Segmentation Fault で落ちます。


    あまり自信はないですが、
    複雑なデータをロードした後の状態が、ヒープの断片化を起こしていて、
    リロードした後、テキスト構文のメモリ確保の段階で
    末尾に丁度 32 バイト分の空きがあるヒープ断片が存在して、
    VS2005 の malloc がそこを優先的に割り当ててしまうということなのでしょうか。

    もしカーネルのバグだとすると、それ以外のライブラリは全て仕様内の動作をしているので、解決策は
    ・SendMessage で送信する文字列の NULL 終端 の次のバイトがヒープの外にならないようにする
    という一点で、そのためには、
    (1) 文字列領域は 1 バイト多く確保する
    or
    (2) 別に用意したヒープ末尾でないバッファに文字列を一旦コピーして、それを SendMessage する
    or
    (3) ヒープ断片化が起こらないように、ヒープは自分で管理する。リロードの度に HeapDestroy -> HeapCreate

    …のどれかをとればいいように思います。

    もちろん、himajin925 さんが仰るような、NULL 終端文字の破壊や、他のバグの可能性も捨て切れないところです。
記事No.8422 のレス / 関連記事表示
削除チェック/

No.8496/Re[27]: NO TITLE
■投稿者/ 開発者 -(2012/11/24(Sat) 20:01:34)
□U R L/http://blog.livedoor.jp/sage_p/archives/50914558.html

    ●himajin925さん
    > 開発者さんの環境では AfxIsValidString などは呼べるのでしょうか?
    > 呼べるようであれば SendMessage の前後で呼んでみてくれませんか。(または相当する関数)
    AfxIsValidStrinとは別の手段ですが確認したところ、前後ともNULLが格納されていました。

    > バッファが Heap の末尾に Alloc されたに場合、文字列の最後に NULL がないのかもしれません。
    文字列終端の不正は、最初に疑った部分であり、その後も機会ある毎に確認しています。
    また、Alloc後にそこに文字列を(もちろん終端NULL付きで)格納していますので、
    Alloc直後の状態は無関係と考えています。

    > また _msize などによって、割り当てられたバイト数を確認する、なども出来ますか?
    確認しました。これもSendMessage の前後共、32バイトでした。

    > ↓malloc のバグだ、という人もいますが…判断できません
    >
    > http://blog.livedoor.jp/sage_p/archives/50914558.html
    よくよく読んでみると、malloc()のバグであると主張しているのではなく、
    自分のプログラムのミスで、malloc()サイズを越えてアクセスしていたが、
    VC++6では幸運にも(正確に言うと不運にもですが)症状が出なかったが、
    VS2005にしたことでそれが顕在化した。・・・という内容の様ですね。

    ●Elekenさん
    解決策のご提示、ありがとうございます!

    > もしカーネルのバグだとすると、それ以外のライブラリは全て仕様内の動作をしているので、解決策は
    > ・SendMessage で送信する文字列の NULL 終端 の次のバイトがヒープの外にならないようにする
    > という一点で、そのためには、
    > (1) 文字列領域は 1 バイト多く確保する
    これは、まさにV6.26aの対応そのものですね。

    > (2) 別に用意したヒープ末尾でないバッファに文字列を一旦コピーして、それを SendMessage する
    今回の格闘の最中、実はこれを実施した記憶があります。
    SendMessage()する前に、別途確保した文字列変数に問題の文字列内容をコピーし、
    それをSendMessage()に送ってみました。すると、症状は出ませんでした。
    ただ、演奏時点の処理負荷が増えるので、対応策としては却下していました。

    場当たり的に試行した私の実験と、論理的に導いたElekenさんの対応策の結果が見事に一致していますので、
    Elekenさんの今回の真因推理はかなりの確度で正しいと思えます。

    > (3) ヒープ断片化が起こらないように、ヒープは自分で管理する。リロードの度に HeapDestroy -> HeapCreate
    私の技術力からして、この対応は継続的にメンテナンスしていく地震がありません。
    じゃなかった、自信がありせん。そういえば先程、横浜で比較的大きな自身がありました。
    じゃなかった、地震がありました。

    > …のどれかをとればいいように思います。
    という訳で、「(1) 文字列領域は 1 バイト多く確保する」を正式な対応とすることが、
    現時点では濃厚です。
記事No.8422 のレス / 関連記事表示
削除チェック/

No.8497/Re[28]: NO TITLE
■投稿者/ himajin925 -(2012/11/24(Sat) 21:53:10)
□U R L/http://blog.livedoor.jp/sage_p/archives/50914558.html

記事No.8422 のレス / 関連記事表示
削除チェック/

No.8498/Re[29]: NO TITLE
■投稿者/ Eleken -(2012/11/25(Sun) 02:23:59)
□U R L/http://blog.livedoor.jp/sage_p/archives/50914558.html

    > では大丈夫のようですね。一応画像を見てください。純粋培養 Muse で SendMessage のエントリーでメッセージの格納位置をダンプしたものです。横 16バイト表示では OK に見えますが、15バイト表示にすると 32バイト目が ?? に、という画像で、同じ状態をキャプチャしたものです(VC++6.0 。ダンプのバグかな)
    個人的には多分、バグなんじゃないかと思います。
    以下は、参考までに、同じ条件で VC++ 2008 でダンプしたスクリーンショットです。
    http://www.adachi.ne.jp/users/2sc1815/muse/a1.png
    http://www.adachi.ne.jp/users/2sc1815/muse/a2.png

    > 32Byte で発生するなら、なぜ他の 8 の倍数バイトで発生しないのかも謎です。
    > それとも、mus ファイルの内容によっては、(見つけていないだけで)発生する場合があるのかな?

    それが一番の謎です。

    ヒープ領域固定の場合、32 byte の malloc がヒープ終端に来るケースは、
    malloc(HeapAlloc) のオーバーヘッドが 8 byte なので、ヒープ残量 40 byte のときです。
    この状態で、30 byte *TEXT の代わりになるような、*TEXT 文の組み合わせも
    存在しそうに思います。

    このときに連続して malloc すると問題になるパターンは、
    (32 byte), (1-8 byte -> 16byte), (13-16byte -> 8 byte) の 3 パターンです。
    しかしながら、30byte *TEXT の代わりに (6byte *TEXT -> 14byte *TEXT) などとしても、問題は起こりません。

    Muse でのケースは、ヒープ断片化を起こしていると考えられるので、より複雑です。
    つまり、malloc 関数には「末尾 40 byte 領域」をアロケートする他に、別の領域を使う選択肢があるからです。(他に、ヒープを広げるという選択肢も!)
    malloc 関数は 前述の状態において、24 byte よりも小さい領域が指定されたとき後者を選択し、
    25-32 byte が指定されたときのみ、前者を選択するのではないでしょうか。
    (メモリ効率上、賢い戦略だと思います)

    このあたりは、malloc のソースコードを見ないとわからないので、
    全く確証が持てません。

    なぜ「32」byte かは、もし仮にマクロ展開時に作る構造体が 25-32 byte なら
    説明がつきそうですが・・・。
記事No.8422 のレス / 関連記事表示
削除チェック/

No.8499/Re[30]: NO TITLE
■投稿者/ himajin925 -(2012/11/25(Sun) 09:37:02)
□U R L/http://blog.livedoor.jp/sage_p/archives/50914558.html

    Elekenさん、開発者さん、おはようございます。

    やはり、システム側のバグっぽいですかね。この VC のダンパと同様の勘違いをシステム側のどこかでやっているのかもしれません。

    しつこいなぁと思われたでしょうが(^_^;)
    これで、「Muse にバグはなかった!」で良いでしょうね。よかったよかった

    (1)純粋培養 Muse の様子を見ていて、症状の起きない 95-Me の互換モードでは、XP でのメモリ管理と違う(ヘッダを見ると、95-Me はバイト単位での割り付けかと想像される→別の API で割り付けてる?)ので問題がおきない?
    (2)XP 以降では 8バイト単位の割り付けになるが、開放されたブロックの再利用の仕方(同じ大きさの開放領域があればそれを使うが、その探し方)が Vista 以降で変更になったそうで、そのせいで XP でだけ発生するのでしょうか。ただ、そうだとすると同様の条件になるケースはありそうだと感じます。XP で顕在化しただけで、Win7 でも…いや何らかの修正がされているのかな?
    (3)ちょうど 40 バイト空いていた場合だけではなくて、
    ちょうど 16バイト空きで 8バイトの文字列…
    ちょうど 24バイト空きで 16バイトの文字列…

    なんていうことが、データによってはありそうですが…そのうち見つかる可能性もあるのかな

    で、やはり +1 とするのですか?
記事No.8422 のレス / 関連記事表示
削除チェック/

No.8500/Re[31]: NO TITLE
■投稿者/ 開発者 -(2012/11/25(Sun) 11:09:27)
□U R L/http://blog.livedoor.jp/sage_p/archives/50914558.html

    ●Elekenさん
    > なぜ「32」byte かは、もし仮にマクロ展開時に作る構造体が 25-32 byte なら
    > 説明がつきそうですが・・・。
    Elekenさんって、まるでシャーロックホームズみたいですね!

    私が掲示板[8493]で書き込んだ、
    > また、機能を削り取ることで不要となった構造体のメンバをコメントアウトしたら、症状が出なくなったこともありました。
    を具体的にお示しします。何か考察のヒントになるかもしれません。

    既に純正培養Museでは3つの構造体しか使用しておらず、
    利用しないメンバーもどんどん剥ぎ取っていますので、
    以下の様な簡素な内容になっています。

    // ノート構造体 --------------------------------
    typedef struct t_note {
    struct t_note* mpz_next; /* 次ポインタ */
    char* mpc_txt; /* コマンド文字列 */
    DWORD mh_tim; /* イベント時刻(ミリ秒) */
    char mc_mid; /* MIDIデータ */
    } T_note;

    // データ展開ワーク ----------------------------
    typedef struct t_work {
    struct t_work* mpz_next; /* 次ポインタ */
    char* mpc_data; /* データ文字列 */
    int mi_num; /* ★行番号 */
    } T_work;

    // 定義マクロリスト ----------------------------
    typedef struct t_macr {
    struct t_macr* mpz_next; /* 次ポインタ */
    char* mpc_name; /* マクロ名(無名マクロの場合はNULL) */
    T_work* mpz_p0; /* ★開始アドレス( { の次) */
    T_work* mpz_p1; /* ★終了アドレス( } の前) */
    char mc_ext; /* ★展開中フラグ */
    } T_macr;

    この中の★印の付いたメンバーは、現時点の純正培養Museでは使用していません。
    そこでこれらの★付きメンバーを剥ぎ取ろうとしたのですが、
    1つでも取り払うと、症状が出なくなってしまいました。

    ●himajin925さん
    > しつこいなぁと思われたでしょうが(^_^;)
    いえいえ、むしろ“真実を追究する”真摯な姿に感動さえしています。
    少々大袈裟かもしれませんが、
    この姿勢は、科学者や検事や医師などの職業を問わず、
    人のあらゆる活動で尊重されるべきものだと思います。

    > で、やはり +1 とするのですか?
    はい。可変長文字列のmalloc()だけ1バイト余分に確保するようにしようと思います。
    ほとんどは、コンパイル時の一時的な確保ですから、永続的にメモリ効率を落とす訳ではないし、
    演奏時にも確保し続けるのは、テキストの表示文字列と譜面モニタの属性表示文字列、
    履歴データのパス、楽譜出力用のタイトル群とスルーコマンド位です。
    そもそもたった1バイトですので、大勢に影響は無いでしょう。

    ※その対応箇所のコメント文には、今回の趣旨が分かるように書いておこうと思います。
     さもないと10年後の自分が見直した時、無駄なメモリを確保している!
     と、戻してしまいそうです(笑)。

    > これで、「Muse にバグはなかった!」で良いでしょうね。よかったよかった
    とても安堵しています。\(^o^)/
    でもこの“戦いの踊り”が終わり、お二人とエキサイティングなやりとりもできなくなると思うと、
    ちょっち淋しい感じもしたりして(苦笑)。

    記念といってはなんですが、現時点の純正培養Museをアップデートしておきました。
    リロード操作は[↑]に限らず、何のキーボードを押下しても起こるようになっています。
    http://www1.c3-net.ne.jp/kato/data/muse.zip
記事No.8422 のレス / 関連記事表示
削除チェック/

No.8502/Re[32]: NO TITLE
■投稿者/ Eleken -(2012/11/26(Mon) 00:59:07)
□U R L/http://blog.livedoor.jp/sage_p/archives/50914558.html

    > 私が掲示板[8493]で書き込んだ、
    >>また、機能を削り取ることで不要となった構造体のメンバをコメントアウトしたら、症状が出なくなったこともありました。
    > を具体的にお示しします。何か考察のヒントになるかもしれません。

    メモリをみたところ、「末尾 40 byte 領域」を持つヒープ断片は
    <24 バイト, <16 バイト, <8 バイトのデータが規則正しく埋まっているようです。
    ご提示頂いた構造体と照らし合わせると、前2者は t_macr, t_work であるようです。
    ( malloc ではサイズが 8 バイト単位に切り上げられます)
    このへんの絶妙なバランスが、「末尾 40 byte 領域」を導いていたと推測しています。

    しかし、すみません、折角ご提示頂いたのですが、これ以上の探求は
    ライブラリの malloc, free の解析を伴うので難しいです。
    これでゲームクリアとさせていただきます(笑)。

    himajin925 さんの仰るような未確認バグデータに対応する意味も含めて、
    +1 バイト余計に確保することはスマートな解決策だと思います。
    malloc 1回で 8〜15 バイトの無駄ですから、1 バイトのオーバヘッドは誤差のようなものだと思います。

    > 記念といってはなんですが、現時点の純正培養Museをアップデートしておきました。
    このソフトウェアが "muse.exe" を名乗っているのを見ると、Muse のアイデンティティってなんだろうと暫し考えてしまいます。
    テキスト領域と鍵盤ひとつあれば Muse なのかな?

    ともあれ、Muse は思っていた以上によく考えられて設計されているのだと、
    ただただ感服するばかりです。
    今回は難しいパズルを見つけた気がして、少し書き込みすぎてしまいました。
記事No.8422 のレス / 関連記事表示
削除チェック/

No.8503/Re[33]: NO TITLE
■投稿者/ るう -(2012/11/29(Thu) 23:31:27)
□U R L/http://blog.livedoor.jp/sage_p/archives/50914558.html

    うわ! しばらく来ないうちにみんな楽しそうなことやってた!
    もう少し早く気付いていれば一緒に遊べたのに……!
記事No.8422 のレス / 関連記事表示
削除チェック/

No.8501/Re[31]: NO TITLE
■投稿者/ 浅川 -(2012/11/25(Sun) 18:27:18)
□U R L/http://www.nns.ne.jp/pri/asakawa/asa/fumen_read/

    これまでのやり取りの過程を読んで。

    > ...やはり、システム側のバグっぽいですかね。...
    システム側の可能性が高くなっているみたいですね。

    原因はわかりませんが、もしかしたら現象を回避する(...できるかどうかわかりませんが...)手法を思いつきましたので書いてみます。

    1.*MARK""と*TEXT""で別々のシステムコールを行っている場合。
      (1)*TEXT""で同様な現象が発生しなければ、
        →*MARK""のテキスト出力部分を*TEXT""と同様にする。

    2.*MARK""と*TEXT""でテキスト同じシステムコールを行っている場合。
      →*MRAK""による、シーク・シーケンスがテキスト出力に及ぼしてる影響も考えられます。
       もしこの場合はシーク・シーケンスとテキスト出力のタイミングを変えてみる。?

    これらは今までElekenさんやhimajin925さんの書き込みを読ませていただいた内容から
    さらに私なりに推察してみたものです。

    もしかしたらこれは的外れかもしれませんが...。

    −−−−−−−−−−−−−−−−−−−
    おっとすみませんでした。
    MuseWikiのでこれらは既に検討されていたのですね。

    −−−−−−−−−−−−−−−−−−−
     あとは、テキスト出力をOSに依存せず、Muse自身からSYSTEM I/Oに出力する手法も思いついたのですが、
    これは対応しようとするOSのバージョンそれぞれ用を書く必要があるかもしれないので勧められないし...。
    ザンネンonz
記事No.8422 のレス / 関連記事表示
削除チェック/


パスワード/

(ダウンロード後、拡張子を .htm or .html にしてください)
[前の20件] [次の20件]

全ページ数 / [0] [1] [2] [3] [4] [5] [6] [7] [8] [9] [10] [11] [12] [13] [14] [15] [16] [17] [18] [19] [20] [21] [22] [23] [24] [25] [26] [27] [28] [29] [30] [31] [32] [33] [34] [35] [36] [37] [38] [39] [40] [41] [42] [43] [44] [45] [46] [47] [48] [49] [50] [51] [52] [53] [54] [55] [56] [57] [58] [59] [60] [61] [62] [63] [64] [65]

使い方 新規投稿 新着記事 ツリー表示 ワード検索 過去ログ 管理モード

- Child Tree -

Muse