fprintfのアサーションチェック

フォーラム(掲示板)ルール
フォーラム(掲示板)ルールはこちら  ※コードを貼り付ける場合は [code][/code] で囲って下さい。詳しくはこちら
はにわ

fprintfのアサーションチェック

#1

投稿記事 by はにわ » 7年前

C++の勉強を始めて日が浅いものです。
fprintfのアサーションチェックで困っており質問しました。

・実行したい処理(mainからsample()を呼び出しています)

コード:

void sample(IDR_CARD_RECOG *pRecog){
FILE *fpw = fopen("./sample.txt", "w");

//fopenのアサーションチェック

fprintf(fpw,"会社名:%ls\n",  pRecog->company);
fprintf(fpw,"会社名の読み仮名:%ls\n",  pRecog->company_kana);

fclose(fpw);

return;
}

上記のexeを叩いたところ、下記のようなエラーが出ました。

Debug Assertion Failed!
Program:(プログラム名).exe
File:f\dd\vctools\crt_bld\self_x86\crt\src\fprintf.c
Line: 55

Expression:(str !=NULL)

For information on how your program can cause an assertion
failure, see the Visual C++ documentation on asserts.
(Press Retry to debug the application)

エラー文よりアサーションチェックが入っていないためと考えたので
アサーションチェックのところにif (fpw == NULL) {exit (1);}を
挿入しデバッグをしました。
すると今度はif文の判定で処理が落ちるようになりました。
これはアサーションチェックを無事通過するにはどのようにすればよいでしょうか?
詳しい方、どうかお願い致します。
(環境はwindows7、visual studio community2015です。)

浅学の私にどうか知恵をお貸し下さい。

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: fprintfのアサーションチェック

#2

投稿記事 by みけCAT » 7年前

if文の判定で処理が落ちるようになったという主張が気になりますが、
とりあえず引数として渡しているポインタは適切に初期化された有効な領域を指していますか?
そうなっていない場合は、そうなるようにするといいと思います。
また、この関数だけでなく、呼び出し元や必要な構造体の定義も含めたコンパイルして問題を再現可能な最小限のコードがあと答えやすいと思います。
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

YuO
記事: 947
登録日時: 13年前
住所: 東京都世田谷区

Re: fprintfのアサーションチェック

#3

投稿記事 by YuO » 7年前

はにわ さんが書きました:エラー文よりアサーションチェックが入っていないためと考えたので
アサーションチェックのところにif (fpw == NULL) {exit (1);}を
挿入しデバッグをしました。
すると今度はif文の判定で処理が落ちるようになりました。
これはアサーションチェックを無事通過するにはどのようにすればよいでしょうか?
呼び出しの間違いがassertによって検知されたために"Debug Assertion Failed!"というダイアログが表示されたのであって,このダイアログを消す事だけを目的にif文を書いても意味がありません。
今回の場合,おそらくはfopenに失敗した結果NULLが返ったにもかかわらず,そのまま実行したがためにfprintf内部のassertに引っかかっています。

fopenは失敗する事があるので,NULLが返った場合はファイルを開けなかった場合にどうするかを考えてコードを作成する必要があります。
もちろん,exit(1);も選択肢の一つですが,それはファイルを作成できないなら終了する,ということを選択した場合の記述になります。
# 処理が落ちる,というのは終了させる選択を自らしたのにそれが想定外であるかのように読めてしまいます。

なお,標準の動作ではないものの,Visual C++のfopenはerrnoを設定します。
このため,NULLが返った場合はerrnoを確認したり,perrorを呼び出して原因を確認するとよいでしょう。

アバター
みけCAT
記事: 6734
登録日時: 13年前
住所: 千葉県
連絡を取る:

Re: fprintfのアサーションチェック

#4

投稿記事 by みけCAT » 7年前

なるほど、strはファイルポインタのことなんですね…。
fprintf debug assertion fail - Stack Overflow
nice variable name, Microsoft, what on Earth were you thinking?
複雑な問題?マシンの性能を上げてOpenMPで殴ればいい!(死亡フラグ)

はにわ

Re: fprintfのアサーションチェック

#5

投稿記事 by はにわ » 7年前

>みけCATさん
返信ありがとうございます。
また質問の指南もありがとうございます。今後、発言する際は参考にさせて頂きます。

>>とりあえず引数として渡しているポインタは適切に初期化された有効な領域を指していますか?
→こちらについては具体的にどのような状態であれば適切と判断できるのでしょうか。


>YuOさん
返信ありがとうございます。
恥ずかしながらperrorの存在を知りませんでした。
下記のようにコードを挿入したところ、メッセージとしてpermission deniedが取得できました。
いろいろ調べて見たのですが、このエラーへの対処法がわかりませんでした。
もしよろしければこのエラーの対処法を教えて頂けないでしょうか。

(冒頭で書き忘れてしまったのですが、問題となっているexeを単体で実行すると
if文を通過しますが、別exeから呼び出すとエラー:permission deniedになってしまいます。)

コード:

 
char *message = "エラーが発生しました";
if (fpw == NULL) {
[tab=30]perror(message);
[tab=30]printf("【ログ】fpw==NULL ポーズ");
[tab=30]getc(stdin);
[tab=30]exit (1);
}

YuO
記事: 947
登録日時: 13年前
住所: 東京都世田谷区

Re: fprintfのアサーションチェック

#6

投稿記事 by YuO » 7年前

permission deinedは権限がない事を示しています。
今回の場合だと,ファイルを書き込む権限がないのでしょう。
出力先がカレントディレクトリになっていますが,書き込む時点でのカレントディレクトリは書き込み権限がちゃんとありますか。
カレントディレクトリは実行ファイルのあるディレクトリのことではないことに注意が必要です。
# ショートカットを作って作業フォルダを指定すれば,そこがカレントディレクトリの初期値になる。

対処法は,権限のあるところを外部から指定するなどして,書き込むか,エラーが起きたらユーザーに別の場所を指定してもらうか,といった方法になるかと思います。
ユーザーのDocumentsなどは特殊な事をしない限り書き込み権限がありますから,拘りがなければそこに必ず書き込むような作りにするのがよいかと思います。

はにわ

Re: fprintfのアサーションチェック

#7

投稿記事 by はにわ » 7年前

>YuOさん
YuO さんが書きました:permission deinedは権限がない事を示しています。
今回の場合だと,ファイルを書き込む権限がないのでしょう。
出力先がカレントディレクトリになっていますが,書き込む時点でのカレントディレクトリは書き込み権限がちゃんとありますか。
カレントディレクトリは実行ファイルのあるディレクトリのことではないことに注意が必要です。
# ショートカットを作って作業フォルダを指定すれば,そこがカレントディレクトリの初期値になる。

対処法は,権限のあるところを外部から指定するなどして,書き込むか,エラーが起きたらユーザーに別の場所を指定してもらうか,といった方法になるかと思います。
ユーザーのDocumentsなどは特殊な事をしない限り書き込み権限がありますから,拘りがなければそこに必ず書き込むような作りにするのがよいかと思います。
→貴重なアドバイスありがとうございました。
権限についていろいろ調査したところ、YuOさんの仰るようにカレントディレクトリの権限が
なぜか読み取り専用になっており、それを解除したところテキストファイルの生成が確認できました。

実際の実装を考えたときは書き込みが必ず実行されるようにしたいと思います。

本件、なんとか解決することができました。
ご丁寧にありがとうございました。

閉鎖

“C言語何でも質問掲示板” へ戻る