2019/11/16(土) [n年前の日記]
#1 [gimp] texturizeプラグインのソースを眺めてる
せっかく Windows10 上で、gimp-texturize プラグインをビルド可能な環境を整えたことだし。ここは一つ、実行すると謎のエラーを出してクラッシュしてしまう原因を調べてみようかと思い立った。
_lmanul/gimp-texturize: Texturize plugin for the GIMP
ということで、チマチマと、printfデバッグ。ソースのあちこちに printf("hoge"); を追記して、ビルドして、GIMP から実行して。どこで不正終了するのか、場所だけでも突き止めようと。
_lmanul/gimp-texturize: Texturize plugin for the GIMP
ということで、チマチマと、printfデバッグ。ソースのあちこちに printf("hoge"); を追記して、ビルドして、GIMP から実行して。どこで不正終了するのか、場所だけでも突き止めようと。
◎ offset.c が怪しい。 :
調べた範囲では、どうやら src/offset.c の、offset_optimal() が呼ばれてからクラッシュしているらしい…。
*1
_gimp-texturize/offset.c at master - lmanul/gimp-texturize
てっきり、calloc や malloc を呼んでいる部分で問題が起きているのではないか、返り値のNULLチェックもしてないし、と予想していたのだけど。
_gimp-texturize/graphcut.cpp at master - lmanul/gimp-texturize
_gimp-texturize/initialiser.c at master - lmanul/gimp-texturize
どうやらそこではなさそうだなと。というのも、NULL が返ってきたらエラーメッセージを出すように修正しても、該当メッセージが全く出てこなかったので。
さておき、offset_optimal() は、difference() という関数を呼び出しているのだけど、この difference() が怪しい。
中では、以下の2つのポインタを使っているのだけど…。
それとも、patchバッファは元画像サイズ (= width_p * height_p * channels) を持つはずだ、という認識が、そもそも間違っているのだろうか…。
_gimp-texturize/offset.c at master - lmanul/gimp-texturize
てっきり、calloc や malloc を呼んでいる部分で問題が起きているのではないか、返り値のNULLチェックもしてないし、と予想していたのだけど。
_gimp-texturize/graphcut.cpp at master - lmanul/gimp-texturize
_gimp-texturize/initialiser.c at master - lmanul/gimp-texturize
どうやらそこではなさそうだなと。というのも、NULL が返ってきたらエラーメッセージを出すように修正しても、該当メッセージが全く出てこなかったので。
さておき、offset_optimal() は、difference() という関数を呼び出しているのだけど、この difference() が怪しい。
中では、以下の2つのポインタを使っているのだけど…。
- patch : 元画像バッファへのポインタ。
- image : 新先作成画像バッファへのポインタ。
それとも、patchバッファは元画像サイズ (= width_p * height_p * channels) を持つはずだ、という認識が、そもそも間違っているのだろうか…。
◎ どうしてそれっぽく動く時もあるのか。 :
しかし、全然関係ない領域を参照しているのに、どうしてそれっぽい画像が出来上がっていたのだろう。
どうやら、difference() は、元画像を配置するのに適した場所を探し出すため、元画像と生成画像のピクセル情報を総当たりで取得して差にして返す関数のようで。たまたま偶然、頓珍漢な領域の情報と差を取ってみたら、それらしい差が得られてしまって、ベストポジションを見つけたつもりになっていた…のではないかと。
しかし、稀に、ユーザプログラムが読んではいけないアドレスから値を読もうとしてしまって、その際には不正終了する…ということではないのかなと。
実行するたびに、生成できたり、不正終了したりと、同じ動作にはならなかったけど。その時々で、周辺のメモリ領域に違う値が入ってたから、動作結果も毎回異なっていたのだな…。たぶん。
どうやら、difference() は、元画像を配置するのに適した場所を探し出すため、元画像と生成画像のピクセル情報を総当たりで取得して差にして返す関数のようで。たまたま偶然、頓珍漢な領域の情報と差を取ってみたら、それらしい差が得られてしまって、ベストポジションを見つけたつもりになっていた…のではないかと。
しかし、稀に、ユーザプログラムが読んではいけないアドレスから値を読もうとしてしまって、その際には不正終了する…ということではないのかなと。
実行するたびに、生成できたり、不正終了したりと、同じ動作にはならなかったけど。その時々で、周辺のメモリ領域に違う値が入ってたから、動作結果も毎回異なっていたのだな…。たぶん。
◎ 飛び出さないようにしてみた。 :
バッファサイズを超えずに値を参照するように修正して動作確認してみた。
落ちない。何度実行しても落ちない。ということは、予想は当たってたようだな…。たぶん。
その代わり、4重ループ内で、1ドット参照するたびに、剰余を使ってアドレスを求め直すようにしてしまったので、処理がとんでもなく遅くなった…。まあ、落ちるよりはマシだろうけど…。
生成画像が正しいかどうかはよく分からず。もっとも、自分の予想が当たっていたとしたら、今までも頓珍漢な画像を作っていたはずで。しかし見ていて特におかしいとは思わなかったのだから、生成結果が正しいかどうかなんて目視で判別はできないだろうなと。
落ちない。何度実行しても落ちない。ということは、予想は当たってたようだな…。たぶん。
その代わり、4重ループ内で、1ドット参照するたびに、剰余を使ってアドレスを求め直すようにしてしまったので、処理がとんでもなく遅くなった…。まあ、落ちるよりはマシだろうけど…。
生成画像が正しいかどうかはよく分からず。もっとも、自分の予想が当たっていたとしたら、今までも頓珍漢な画像を作っていたはずで。しかし見ていて特におかしいとは思わなかったのだから、生成結果が正しいかどうかなんて目視で判別はできないだろうなと。
*1: DOS窓に printf で文字列が表示されるタイミングがずれてなければの話だけど。
[ ツッコむ ]
以上です。