少しイジメテミタ
おっきな SWF ファイル
% php sample/swfdump.phps "魔理沙は大変なものを盗んでいきました.swf" > /dev/null malloc: ;_;
えっと… swfed は -DMALLOC_DEBUG を付けてコンパイルすると、 free し忘れを検出する為に、malloc/free の管理テーブルを作ります。
そのサイズが足りませんでした。
とりあえずサイズを倍に拡張して足りたので、それで… (このやり方はかっこ悪いので、もう少し考えます)
デバッグ用とはいえ分かりにくいので、エラーメッセージに table full を追加してます。
中途半端な SWF ファイル
% bcut game.swf 0 900000 > game-hankake.swf % php sample/swfdump.phps game-hankake.swf swf_object_input: uncompress failed by unknown reason magic=CWS version=9 file_length=1063877 rect=(0, 0)-(0, 0) (f_size=0) frame_rate=0.0 frame_count=0 XXX (3) ptr=0xb79ac008 (/home/yoya/svn/swfed/src/swf_object.c, 61)
メモリリーク発見。(☆▽☆)
zlib 伸張に失敗した時の異常系で、 zlib 用に確保した領域を free し忘れてました。
対処後
% php ~/svn/swfed/sample/swfdump.phps game-hankake.swf swf_object_input: uncompress failed by unknown reason magic=CWS version=9 file_length=1063877 rect=(0, 0)-(0, 0) (f_size=0) frame_rate=0.0 frame_count=0
よしよし。
中途半端な PNG ファイル
% bcut kuriboo4.png 0 166300 > kuriboo4-hankake.png % php sample/swfdump.phps game.swf <略> [38] tag=DefineBitsLossless2(36) length=110 image_id=30 format=3 width=62 height=18 colormap_count=16 rgba colormap exists indices exists <略> % php sample/swfreplacepngdata.phps game.swf 30 kuriboo4-hankake.png > /dev/null png_data_read_func: ! png_buff->data_offset(160789) + size(5516) <= png_buff->data_len(166301) libpng error: png_read_read_func failed
アボートしました
あちゃー… でも、libpng のエラーハンドリングは setjmp 方式なんですよね…
libpng の man(3) の説明
See the discussion on libpng error handling in the Customizing Libpng section below for more information on the libpng error handling. If an error occurs, and libpng longjmp’s back to your setjmp, you will want to call png_destroy_read_struct() to free any memory. if (setjmp(png_jmpbuf(png_ptr))) { png_destroy_read_struct(&png_ptr, &info_ptr, &end_info); fclose(fp); return (ERROR); }
でもって、
If you read the file from different routines, you will need to update the jmpbuf field every time you enter a new rou- tine that will call a png_*() function.
スコープがあってればイイじゃない。ってとこかしら。
setjmp
png_bytepp png_image_data = NULL; <略> if (setjmp(png_jmpbuf(png_ptr))) { fprintf(stderr, "pngconv_png2lossless: libpng error jump occured\n"); png_destroy_read_struct(&png_ptr, &png_info, NULL); if (png_image_data) { for ( y = 0 ; y < png_height ; y++) { free(png_image_data[y]); } free(png_image_data); } return NULL; } <略> png_image_data = (png_bytepp) malloc(png_height * sizeof(png_bytep)); for (y=0; y < png_height; y++) { png_image_data[y] = (png_bytep) malloc(png_get_rowbytes(png_ptr, png_info)); }
としてみたら、png_image_data が free 出来ず。
何でだろうと「setjmp ローカル変数」で google 様にお伺いを立てた所、
- setjmp/longjmpとローカル変数
xにvolatileをつけ忘れると、こういうこと↑になります…
ナルホド。最適化とレジスタの罠か… やっぱり setjmp キライ
abort しちゃった方が全てを忘れられて楽だけど、そんな訳にもいかないので、頑張って対処します。
discards qualifiers from pointer target type
/home/yoya/svn/swfed/src/swf_png.c: In function 'pngconv_png2lossless': /home/yoya/svn/swfed/src/swf_png.c:166: warning: passing argument 1 of 'png_destroy_read_struct' discards qualifiers from pointer target type /home/yoya/svn/swfed/src/swf_png.c:166: warning: passing argument 2 of 'png_destroy_read_struct' discards qualifiers from pointer target type
volatile つけたら怒られちゃった… ><
仕方が無いので cast 付けて黙らせます。
png_destroy_read_struct((png_structpp) &png_ptr,
(png_infopp) &png_info, NULL);
何だかなぁ…
might be clobbered by 'longjmp' or 'vfork'
/home/yoya/svn/swfed/src/swf_png.c:234: warning: argument 'image_data' might be clobbered by 'longjmp' or 'vfork'
image_data は setjmp と関係ない所で使ってるのに…
どうしよう…
最後に
やっぱり setjmp キライ