再配布 > ページ境界処理テスト用

「再配布/ページ境界処理テスト用」の編集履歴(バックアップ)一覧に戻る

再配布/ページ境界処理テスト用 - (2008/07/02 (水) 14:38:30) のソース

***ページ境界処理テスト用プラグイン
-作者:スレ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()
ツールボックス

下から選んでください:

新しいページを作成する
ヘルプ / FAQ もご覧ください。