***ページ境界処理テスト用プラグイン -作者:スレ46≫876氏 -一次配布元:[[スレ46≫911>http://pc11.2ch.net/test/read.cgi/software/1212669676/911]] -技術的な話 876 :名無しさん@お腹いっぱい。:2008/07/01(火) 05:46:53 ID:rU3tuL6Q0 今気がついたんだが、99d3になってまた(まだ?)rgb2yc()の処理がおかしい気がするな。 pixelpに投げたポインタから少なくとも8バイト分は一気に読みに行くようで 確保したメモリ領域が8バイトの倍数でないと、確保されていないところまで読みに行って 0xc00000005の例外が出る。オフセットアドレスは0x00037e1aだそうだ。 てっきり作りかけの自作プラグインが悪いのかと思っちまった・・・ 877 :名無しさん@お腹いっぱい。:2008/07/01(火) 06:14:37 ID:rU3tuL6Q0 ごめん、分かりにくいかもしれないので補足。 検証のためにやったことは、 1. バッファの末尾(BMP的には先頭)の1ラインを一気に処理→画像によってOKだったりNGだったり 2. 1.でNGな画像のバッファの中間の1ラインを一気に処理→OK 3. 1.でNGな画像のバッファの末尾のラインの左端1ピクセル目だけ処理→OK ・・・(中略)・・・ 4. 1.でNGな画像のバッファの末尾のラインの右端から3ピクセル目だけを処理→OK 5. 1.でNGな画像のバッファの末尾のラインの右端から2ピクセル目だけを処理→NG 24bit BMPを扱っているので、右端から3ピクセル目だと 確保されているバッファは残り9バイトだが 2ピクセル目では残り6バイトになる。 あれ、よく考えたら>>876説では1.でNGになった画像が横512ピクセルなのと矛盾するな。 徹夜で頭がボケてら・・・ ちなみに横が4096ピクセルとか848ピクセルとか378ピクセルとか22ピクセルのは大丈夫だった。 878 :名無しさん@お腹いっぱい。:2008/07/01(火) 06:20:36 ID:z1borOEQ0 >>877 そのバッファはどうやって確保してる? メモリは4KBのページ単位で確保されているので、 うまい具合にバッファの末尾がページの最終バイトになるようにしないと、 ちゃんと再現しないよ? 879 :名無しさん@お腹いっぱい。:2008/07/01(火) 06:22:53 ID:z1borOEQ0 まさかとは思うけど、 BMPは1ラインが4バイトの倍数になるようにパディングが必要 ってことを忘れていて、あなたが確保したメモリが足りない・・・だったりする? 880 :名無しさん@お腹いっぱい。:2008/07/01(火) 06:24:48 ID:r2l78CL70 >>824 マジできてる━━━━(Д゚(○=(゚∀゚)=○)Д゚)━━━━!!!! プラグインの作者様達乙なのです。 881 :名無しさん@お腹いっぱい。:2008/07/01(火) 06:28:47 ID:z1borOEQ0 ごめん、自分も眠くてボケてた。 >>878と>>879は、なかったことにして。 882 :名無しさん@お腹いっぱい。:2008/07/01(火) 06:31:01 ID:rU3tuL6Q0 >>878-879 朝早くからレスありがとう。 バッファは原始的にmalloc()してる。 ただ、rgb2yc()は元のデータがBMPだったかどうかは全然関係ないわけで、 BMPの読み込みが正常に完了してる以上はメモリが足りないことはないと思うんだな。 もうちょっと追試してみたが横じゃなくて縦も関係あるようだ・・・ 512x47→OK 512x48→NG いったい何が悪いんだ・・・orz 883 :名無しさん@お腹いっぱい。:2008/07/01(火) 06:35:18 ID:z1borOEQ0 >>882 NGなのは確実にNGとしても、 OKなのは、偶然そのアドレスが有効だったので、たまたま動いているだけ、だと思う。 884 :名無しさん@お腹いっぱい。:2008/07/01(火) 06:36:42 ID:rU3tuL6Q0 ポインタをよーく観察したら、やっぱりページ境界が関わっているようだ。 バッファの先頭がページの先頭になるとして、 512x47の画像を読み込んだ時にはバッファの末尾がページ境界に来ないが、 512x48の画像だとバッファの末尾がちょうどページ境界になる。 885 :名無しさん@お腹いっぱい。:2008/07/01(火) 06:39:39 ID:rU3tuL6Q0 書き込むとレスが付いてる法則・・・ >>883 自分もそういう結論に達した。 やっぱり原因はrgb2yc()の中にあるようだ。とりあえず修正されるまでの間は バッファがページ境界ぴったりに収まってしまう場合もう1ページ余分に確保するしかないか・・・ 886 :名無しさん@お腹いっぱい。:2008/07/01(火) 06:41:46 ID:z1borOEQ0 あーうまく1レスにまとめて書けなくて連投でゴメン OKなのは、本当にOKなのと、たまたま動いているだけの2つ。 たまたま動いているのがNGになるようにするためには、 Win32APIのVirtualAllocを使って、 1バイトでもオーバーランしたらページアクセス違反になるようにする。 具体的には、 VirtualAllocにMEM_RESERVEを付けてアドレス空間を予約する VirtualAllocにMEM_COMMITを付けてメモリを確保する メモリを確保している範囲と予約しただけの範囲の境目が、 バッファの終わりになるようにRGBデータをメモリに書き込み、 rgb2ycを呼び出す。 887 :名無しさん@お腹いっぱい。:2008/07/01(火) 07:21:57 ID:rU3tuL6Q0 >>886 それの確実なやり方なんだけど、1回目ではわざと大きめに予約しておいて、 2回目で1回目に返ってきたアドレスをぶち込んでサイズは画像ぴったりに確保、でおk? 一応上のやり方で確保してテストしてみた。 だけど・・・不思議なことに挙動に変化はなかった。 そして予想通り、確保する領域を1ページだけ増やしたら動いた。 888 :名無しさん@お腹いっぱい。:2008/07/01(火) 07:44:10 ID:z1borOEQ0 >>887 2回目のときのサイズは画像ピッタリでOK (OS側がページサイズに切り上げてくれる) ただし、画像の末尾がページ境界になるように、画像を配置する。 たとえば画像が100バイトだとしたら、 100バイト+4Kバイトを予約 → 8Kバイトが予約される そのアドレスで100バイトをコミット → 4Kバイトがコミットされる そのアドレスから、4096 - (100 % 4096) バイト 進んだ位置に、 画像100バイトの画像をコピー。その100バイトの先頭をrgb2ycに渡す こんな感じです。 889 :名無しさん@お腹いっぱい。:2008/07/01(火) 08:05:22 ID:rU3tuL6Q0 >>888 おk 再現できた。 アクセス違反の起こったアドレスはすべて4kページ境界。 890 :名無しさん@お腹いっぱい。:2008/07/01(火) 08:28:24 ID:z1borOEQ0 乙 あとは作者に連絡するだけですね。 891 :名無しさん@お腹いっぱい。:2008/07/01(火) 08:44:05 ID:y/RFWf640 >>876-890 おまいらそれ何語でしか? 892 :名無しさん@お腹いっぱい。:2008/07/01(火) 09:00:55 ID:rU3tuL6Q0 >>890 朝っぱらから検証手伝ってくれて㌧ 今はメールしか連絡手段ないのか・・・ 893 :名無しさん@お腹いっぱい。:2008/07/01(火) 09:01:53 ID:WodilLXp0 サルでもわかるように説明していただけるとありがたい 99d3地雷? 895 :名無しさん@お腹いっぱい。:2008/07/01(火) 09:35:32 ID:rU3tuL6Q0 >>893 サルが分かるかは自信がないが・・・ どのバージョンからそうなったかについては調べていないが、 AviUtlに用意されている rgb2yc() という関数を使ってRGBとYCrCbの変換をしている プラグインは、作業用メモリの確保のやり方次第で地雷を踏む可能性があることが分かった。 ひょっとすると同じことが逆変換の yc2rgb() にも言える可能性がある(これも要調査)。 ただ、謹製のテロップフィルタは地雷ではなかった。 標準の構成のまま使うならおそらく問題はないだろう。 BMP画像を扱う外部のプラグインは地雷を踏む可能性が比較的高いので要注意。 ちなみに、地雷を踏んでも例外のダイアログで「はい」を選べばそこから安全に終了できる。 896 :名無しさん@お腹いっぱい。:2008/07/01(火) 10:13:56 ID:SCJUP7yc0 d3は別に地雷ってわけじゃないよ。 ただプラグイン使うと例外エラー起きちゃうことがあってそれがとにかく腹が立つだけさ。 プラグイン使わないなら特にきにしなくていいんじゃないかな。 俺もよくは知らないけど。 897 :名無しさん@お腹いっぱい。:2008/07/01(火) 10:27:55 ID:KlMp66tr0 プラグイン作成するときはメモリを少し余分に確保しておけってことかな? 他のソフトもそうだけど、バグは絶対あるものと思って保険かけとけと。 898 :名無しさん@お腹いっぱい。:2008/07/01(火) 10:28:58 ID:DVkFJgPM0 なんだ、要するに今日は快晴ってことか・・・ 899 :名無しさん@お腹いっぱい。:2008/07/01(火) 10:43:50 ID:WodilLXp0 >>895-896 なんとなく漏れは大丈夫そうかな? 解説㌧ d4だか99eだかわからんが早く直してくれるといいな 900 :名無しさん@お腹いっぱい。:2008/07/01(火) 11:49:33 ID:/EXYkM9/0 なんだシークさせてくとエラーだすのはSSE2のせいかとおもってたぜ 911 :876:2008/07/01(火) 18:22:33 ID:rU3tuL6Q0 例の件、実感湧かない人も多いんじゃないかと思うので テスト用のプラグインフィルタを作ってみた。 ttp://www2.uploda.org/uporg1517234.zip.html DLパスは名前 ちなみに手元のテストでは99a3まで全部再現した。 従って99d2での修正は関係ない模様。 ---- #comment()