人力検索はてな
モバイル版を表示しています。PC版はこちら
i-mobile

libpngでのPNGファイルの読み込み方について質問です。

こちらのサイト(http://gmoon.jp/png/#program_reading)を参考にしながら、libpng(ver.1.6.8)を使ってPNGファイルを読み込むプログラムをVisualStudio2013で書いています。

プロジェクトのlibpngとのリンクは正常にできているのですが、PNGファイルのヘッダを読み込むところとIHDRチャンクから情報を取得するところ(*1)で、以下のようなウィンドウ(*2)が出てプログラムが止まってしまいます。

*1) - - - - - - - - -
png_read_info(png_ptr, info_ptr);
png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type, &interlace_type, NULL, NULL);

*2) - - - - - - - - -
「ハンドルされない例外が 0x77188E19 (ntdll.dll) で発生しました(libpng_test1.exe 内): 0xC0000005: 場所 0x00000014 への書き込み中にアクセス違反が発生しました。」


インクルードしているヘッダは以下です。
#include <png.h>

関数の使い方が参考のサイトのバージョンとは違うのでしょうか?
こういった状況のlibpng関連の参考文献は全然見当たらず、にっちもさっちもいかなくなってしまったので質問いたしました。どうすればよいのでしょうか…。よろしくお願いいたします。

●質問者: onigiriTurnA
●カテゴリ:コンピュータ
○ 状態 :終了
└ 回答数 : 1/1件

▽最新の回答へ

1 ● cx20
ベストアンサー

場所 0x00000014 への書き込み中にアクセス違反が発生しました。

このエラーは、不正なメモリアクセスをした際に発生します。
恐らくは、今回のケースはメモリ確保されていない構造体のメンバ(0x14=20バイト目)にアクセスして落ちているものと推測されます。

以下は、事象説明の為の疑似的なコードになります。

typedef struct _struct_test
{
 char field1[10];
 char field2[10];
 char field3;
} struct_test;

void test()
{
 struct_test* p_test = NULL;
 p_test->field3 = 1; // 0x00000014 への書き込み中にアクセス違反となる
}
<構造体 p_test のメモリレイアウト>
0x00000000 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??
0x00000010 ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ?? ??
 ^^ ← ここに書き込もうとするとアクセス違反となる

Release ビルドだと、エラー箇所が特定しづらいので、Debug 版で試してみてはいかがでしょうか。

どうしても、Release ビルド版で調査したいということでしたら、システム環境変数に
f:id:cx20:20140203015649p:image

SET _NT_SYMBOL_PATH=symsrv*symsrv.dll*c:\localsymbols*http://msdl.microsoft.com/download/symbols

を追加してみてください。

これは、デバッグシンボルと呼ばれるもので、これを追加することで、呼び出し履歴(コールスタック)に、C のランタイムの関数名や OS の API 名が表示されるようになり、どこで落ちているのかを調査するのに役立ちます。

■ シンボルを使用したデバッグ
http://msdn.microsoft.com/ja-jp/library/bb694540(v=vs.85).aspx

f:id:cx20:20140203022344p:image
ちなみに、今回のケースでは、ファイル読み込みの際に、落ちているとのことなので、構造体としては FILE ポインタが怪しい気がします。。。

例えば、VC++ で古い C のコードをコンパイルしようとすると、fopen 関数は fopen_s 関数に置き換えるように、警告が表示されるかと思います。

この時の、コードの置き換えが正しく行われているか、再度確認してみては如何でしょうか。

■ fopen_s、_wfopen_s
http://msdn.microsoft.com/ja-jp/library/z5hh6ee9.aspx


onigiriTurnAさんのコメント
解答ありがとうございます!感謝いたします。 「不正なメモリアクセスの概念について」 丁寧な解説をありがとうございます。雰囲気は分かったのですが、この状態でなぜ"char field3"のメモリにかぎってメモリを確保できないのかが分かりません…。一見アロー演算子でいけそうに見えてしまいます。 提示していただいたコードを試しに自分で変更してみたのですが、エラーは出ずとも変な文字が出てしまいました…。初歩的な質問でお恥ずかしいです。 //構造体宣言は無変更// void main() { _struct_test test; struct_test* p_test = NULL; p_test = &test; p_test->field1[0] = 100; p_test->field3 = 1; cout << p_test->field2[0] << "\n"; cout << p_test->field3 << "\n"; } 「エラー箇所について」 ウィンドウに気をとられて記入し忘れていました。呼び出し履歴には、 ------------------- ntdll.dll!77508e19()不明 [下のフレームは間違っているか、または見つかりません。ntdll.dll に対して読み込まれたシンボルはありません。] [外部コード] libpng16.dll!png_default_read_data(png_struct_def * png_ptr, unsigned char * data, unsigned int length) 行 60C >libpng16.dll!png_read_sig(png_struct_def * png_ptr, png_info_def * info_ptr) 行 134C libpng16.dll!png_read_info(png_struct_def * png_ptr, png_info_def * info_ptr) 行 104C libpngTest.exe!main() 行 49C++ [外部コード] ------------------- というメッセージが出ています。厳密には、libpngのpngrutil.c内、 ------------------- /* Read and check the PNG file signature */ void /* PRIVATE */ png_read_sig(png_structrp png_ptr, png_inforp info_ptr){ ------------------- という関数の中で落ちているようです。 また、fopen関数(警告無視)、fopen_s関数の両方で試してみたのですが、同じ現象が出てきます。 自分にはそもそも基礎知識が足りないという事が良く分かってきました…。 この件やメモリアクセスに関してググっておくべき単語等はありますでしょうか。

cx20さんのコメント
> 「不正なメモリアクセスの概念について」 > 雰囲気は分かったのですが、この状態でなぜ"char field3"のメモリにかぎってメモリを確保できないのかが分かりません…。 少し説明が分かりにくかったかも知れません。 >|c| _struct_test test; struct_test* p_test = NULL; p_test = &test; p_test->field1[0] = 100; p_test->field3 = 1; ||< 上記のコードであれば、p_test にメモリ(構造体)が割り当てられている為、問題にはなりません。 自分が例示したかったのは、 >|c| struct_test* p_test = NULL; p_test->field3 = 1; ||< のように、p_test にメモリ(構造体)が割り当てられていない状態で メンバ(field1?3)にアクセスすると、メモリの実体が存在しない為、アクセス違反で落ちます、という説明をしたかっただけですので、field3 だからメモリを確保できていない、というわけではありません。 > この件やメモリアクセスに関してググっておくべき単語等はありますでしょうか。 特段、ググる必要は無いですが「Debug ビルド」をして「デバッグ実行」をするのが定石かと思います。 「デバッグ実行」であれば、呼び出し履歴から、対象のコードに移動できますし、変数をウォッチすることで、問題の手がかりになるかと思います。 あと、呼び出し履歴を見て気になったのですが、 > libpngTest.exe!main() 行 49 C++ C++ と表示されているということは、ソースは *.cpp の形式(C++)で作成されているようですね。 http://gmoon.jp/png/#program_reading オリジナルのサンプルは *.c の形式(C言語)だったかと思いますので、 原因の切り分けの1つとして、一旦は、サンプルと同じもの(*.c)をコンパイルしてみてはいかがでしょうか。 (*.c → *.cpp への移植の際に、不具合が入り込んでいる可能性も考えられる為)

匿名回答0号さんのコメント
単にファイル"test.png"を開けていないのが原因に100カノッサ。 >|c| fp = fopen("test.png", "rb"); // まずファイルを開きます ||< fopen()がNULLでない値を返していますか? 呼び出し履歴から見てfread()でアクセス違反が起きているのではないでしょうか。

cx20さんのコメント
試したところ、 fp が 0xfffffff0 の場合(恐らく、初期化されていない値の場合)に同じエラーが発生しました。 Anonymous さんのご指摘のように fopen がが失敗している可能性が高そうです。

onigiriTurnAさんのコメント
お二人ともありがとうございます。 どうやらlibpngのビルド方法に問題があったようです。散々お騒がせいたしました。 結果的には関係ありませんでしたが、構造体のメモリアクセスの概念など、本当に勉強になりました。ありがとうございました。
関連質問

●質問をもっと探す●



0.人力検索はてなトップ
8.このページを友達に紹介
9.このページの先頭へ
対応機種一覧
お問い合わせ
ヘルプ/お知らせ
ログイン
無料ユーザー登録
はてなトップ