• ベストアンサー

Windows APIでおかしな事になる。

Windows APIでプログラミングをしています。 Windows APIでプログラミングをしています。 char*型の文字列を表示させようと、このように記述しました。 const char * y; y=f(); SelectObject(hdc , hFont); SetBkColor(hdc , RGB(255 , 255 , 255)); wsprintf( str, "名前は、%s", y ); TextOut(hdc , 300, 20, str, lstrlen(str)); すると、表示できたのはいいのですが、 タイトルバーをクリックしてウィンドウを広げたり、別のウィンドウを一番前に持ってきて、 その後、そのウィンドウを出したりすると、エラーが出て、強制終了になってしまします。 何か問題はありますか? ちなみに、strの宣言はこのようになっております。 static TCHAR str[64]; あとですが、 wsprintf( str, "名前は、%s", y ); この部分のyを&yに変えると、エラーは起こりませんが、 変な文字が表示されてしまいます。 ウィンドウを少し操作すると、その文字がまた変な文字に変わります。 何が原因でしょうか。

質問者が選んだベストアンサー

  • ベストアンサー
  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.4

★アドバイス >表示はされますが、その後、ウィンドウを閉じたりすると問題が発生してしまします。  ↑  恐らくは次の1行が原因です。 >strncpy(x, tempone, strlen(tempone));  ↑  この1行は『tempone』という文字列を『x』にコピーしていますが  文字列の末尾を表す '\0' は何処で書き込みました。  書き込んでいませんよね。  これが原因です。 改善策: ・(1)malloc() ではなくて calloc() 関数を使って確保する。  (2)『tempone[ strlen(tempone) ] = '\0';』の1行を追加する。  単純にこれだけです。 その他: ・fopen() したのに fclose() していません。  必ず f() 関数を抜ける前に fclose() して下さい。  修正箇所は  (1)最後の『exit(1);』する前に fclose() します。  (2)最後の『return x;』する前に fclose() します。  ※(1)は exit() して終了しているので特に fclose() 記述しなくても良いです。  ※あと Windows のプロシージャ内なら ExitProcess() を記述したほうが良いです。   でも exit() 関数は API の ExitProcess() を内部で呼んでいそうだね。 ・それからソースを見ての感想として次の1行は strncmp() 関数を使ったらどうかな。 >if( chars[i] == 'm' && chars[i+1] == 'o' && chars[i+2] == 'd' && chars[i+3] == 'u' && chars[ i+4] =='l' && chars[i +5]=='e' && chars[i + 6] ==' '){  ↑  この1行を『if ( !strncmp(&chars[i],"module ",7) ){』とします。  この方が分かりやすいですよ。 ・あと『読み込み』時に chars[] 配列の容量をチェックして下さい。  『mux2.v』ファイルが 1000 バイト以上だとメモリを破壊してしまいます。注意! ・以上。少々おせっかいな事を3つ『その他』で助言しておく。

noname#142813
質問者

お礼

懇切丁寧な回答どうもありがとうございます! flose;を記入したら、問題は解決致しました! ありがとうございました!

noname#142813
質問者

補足

↓の訂正です。 fclose(fp); を追加後、問題解決しました。 ありがとうございました!

その他の回答 (6)

  • simi5
  • ベストアンサー率71% (5/7)
回答No.7

問題は解決されたようですが、一つ気になった点を上げます。 関数f()の戻り値ですが、ファイルのオープンに失敗した場合にEXIT_FAILUREを返していますが、呼び出し側でエラーチェックをしていないですね。 f()の呼び出し後、wsprintf( str, "名前は、%s", y ); が実行されているので、ファイルがオープン出来なかった場合はここで落ちる可能性が高いです。 >fclose(fp); >を追加後、問題解決しました。 との事なので、おそらくウインドウの捜査をして2回目の実行で開きっぱなしのファイルを重複オープンしようとしてエラーになっていたのでしょう。 ファイルのクローズも必要ですが、各所でのエラーチェックも重要です。 また、char*型にEXIT_FAILUREを返すのもあまり良くないです。 この場合はNULLを返すようにして、呼び出し側では以下のようにします。 char* y = f(); if(y){ /* 正常だった時の処理 */ SelectObject(hdc , hFont); SetBkColor(hdc , RGB(255 , 255 , 255)); wsprintf( str, "名前は、%s", y ); TextOut(hdc , 300, 20, str, lstrlen(str)); } EXIT_FAILUREは規格上は0以外のなんらかの整数値のようなので、有効なポインタの判別には使えません。

noname#142813
質問者

お礼

ありがとうございます。 とても参考になりました。 一度試してみます。

noname#142813
質問者

補足

次のステップにて、エラーが出てしまったので、 EXIT_FAILUREを0に直したところ、エラーは出なくなりました。 どうもありがとうございました。

  • aris-wiz
  • ベストアンサー率38% (96/252)
回答No.6

>メッセージボックスで実行してみましても同じ結果になります。 >表示はされますが、その後、ウィンドウを閉じたりすると問題が発生してしまします。 表示できるかではなく、どのステップまで実行されているのかを 確かめてください。 どんなコードを書いているのか少し判りづらいですが、 ウィンドウサイズや、フォーカスの変化による 無効領域の発生が原因だと思われます。 無効領域が発生した場合、通常はプロシージャの中で WM_PAINTをハンドルして再描画を行います。

参考URL:
http://www.geocities.jp/ky_webid/win32c/014.html
noname#142813
質問者

お礼

回答どうもありがとうございます。 無事、問題は解決致しました^^

  • Oh-Orange
  • ベストアンサー率63% (854/1345)
回答No.5

★追記。 ・良く考えたら最後に NULL 文字を書き込むよりは strcpy() 関数を使えば良いです。  strncpy() ではなく strcpy() 関数に差し替えるだけで問題は解決すると思います。 ・以上。

noname#142813
質問者

お礼

ありがとうございます! これも試してみます。

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.3

メッセージボックスなどでどこまで期待したとおり実行されているのか確認なさったほうが良いでしょう 関数fの中がおかしいのか、戻り値のyがおかしいのか ・・・ デバッグ可能な統合環境で開発することも検討してみましょう

noname#142813
質問者

お礼

メッセージボックスで実行してみましても同じ結果になります。 表示はされますが、その後、ウィンドウを閉じたりすると問題が発生してしまします。 回答ありがとうございます。

  • php504
  • ベストアンサー率42% (926/2160)
回答No.2

y=f(); このf( )がわからないと答えられないでしょう f( )でmallocしてそのポインタを返しているのでしょうか それならy の free( )はどこでしているのでしょうか mallocしたらfreeしましょう

noname#142813
質問者

お礼

fの内容は次のようになっております。 free(y); をどこにおいても同じ結果になります。 const char * f(){ FILE *fp; char chars[1000]; /* 読み込む文字 */ char temp[1000]; int count, i,read,j,k,l=0,flag; char tempone[1000],temptwo[1000],tempthree[1000],tempfour[1000],tempfive[1000]; char ch = ' '; char *x; fp = fopen("mux2.v", "r"); if (fp == NULL){ printf("sample.txt を開けませんでした。\n"); return EXIT_FAILURE; } count = 0; /* 読み込み */ while ((read = fgetc(fp)) != EOF) { chars[count] = read; count++; } flag = 1 ; for( i = 0 ; i <= 1000 ; i++ ){ if( chars[i] == 'm' && chars[i+1] == 'o' && chars[i+2] == 'd' && chars[i+3] == 'u' && chars[ i+4] =='l' && chars[i +5]=='e' && chars[i + 6] ==' '){ for( j = 0 ; j <= 6 ; j++ ){ printf("%c",chars[i + j]); } for( k = 7 ; k <= 20 ; k++ ){ if( chars[i + k] != '(' ){ temp[i + k] = chars[i + k]; printf("%c",chars[i + k]); }else{ temp[i+k] = '\0'; } } for( k = 7 ; k <= 20 ; k++ ){ if( chars[i + k ] != '(' ){ printf("%c",temp[i + k ]); }else{ break; } } printf("\t"); if( flag == 1 ){ for( k = 7 ; k <= 20 ; k++ ){ tempone[ l ] = temp[ i + k ]; l = l + 1; } } if( flag == 2 ){ for( k = 7 ; k <= 20 ; k++ ){ temptwo[ l ] = temp[i + k ]; l = l + 1; } } if( flag == 3 ){ for( k = 7 ; k <= 20 ; k++ ){ tempthree[ l ] = temp[i + k ]; l = l + 1; } } if( chars[i] == EOF ){ break; } flag = flag + 1; l = 0; } } x = malloc(strlen(tempone) + 1); if(x == NULL) { exit(1); } strncpy(x, tempone, strlen(tempone)); return x; }

  • redfox63
  • ベストアンサー率71% (1325/1856)
回答No.1

変数yに対して constを宣言していますが本当に const宣言が必要なのでしょうか 関数fの戻り値を代入していますが 毎回実行する必要があるのでしょうか const宣言で変更できないchar型のポインタを使うならこのイベントの関数の外で const char *y = f(); といった宣言をしてみてください もし fが何かのクラスのメンバー関数ならstatic属性を付加しないといけないでしょう 一般的な変数なら char *y; といった宣言のほうが良いように思いますよ yを &yに変更してしまうとぜんぜん違う意味になります yのままなら 文字列を示すポインタ &yにすると このポインタが保存されているメモリのアドレス となって wsprintfの引数として %sを表すには不適格です

noname#142813
質問者

お礼

char *y; に変えてみても結果は同じでした。 回答ありがとうございます。

noname#142813
質問者

補足

別の関数で、 malloc関数を使っているのは何か関係がありますでしょうか。

関連するQ&A