プロが教える店舗&オフィスのセキュリティ対策術

Cのプログラムを作成しているのですが、どうしても分からないので質問させてください。

以下のように、日本語を含んだテキストファイルから一行読み込み、その行の中のある部分だけ切り取るという関数を作ったのですが、メモリを解放する段階(free関数の部分)で動作が止まってしまいます。
どうすれば良のでしょうか?

使用環境は、windows vista, visual C++ Express Editionです。
よろしくお願いします。

char mid(wchar_t *str, int st, int ed, char result[128])
{
wchar_t *ans = (wchar_t*)malloc(sizeof(wchar_t));

wcscpy(ans,&str[st]);
ans[ed-st+1] = L'\0';

wcstombs(result, ans, 128);
printf("result = %s \n",result);

free(ans);
ans = NULL;
return 0;
}

*str:日本語を含んだ文字列(1行分)
st:切り取りを始端
ed:切り取りの終端
ans:切り取り結果
result:切り取り結果(マルチワイド文字列)

また、何故かワイド文字列で定義した「ans」のままではうまくいかず、マルチワイド文字列「result」だとうまくいきませんでした。
これの理由も、できればお願いいたします。

A 回答 (8件)

や, malloc で確保する量を間違っているのではないかと思われます>#1.


ちゃんと「必要な分」だけ確保していますか?
ちなみに最後から 2行前の文は意味不明.

この回答への補足

回答ありがとうございます。

確保する量をwcscpyでコピーする文字数分にして、再度実行してみましたが、やはり動作が止まってしまいました。
wcstombs(result, ans, 128);
printf("result = %s \n",result);
の表示はされているので、そこまでは問題無いかと思っていたのですが・・・。
「必要な分」=「コピーする文字数分」で良いのでしょうか?

補足日時:2009/01/09 12:06
    • good
    • 0

それだけでは「十分に確保している」かどうかはわかりません. malloc している行をどのように修正したのか見せてください.


あと
何故かワイド文字列で定義した「ans」のままではうまくいかず、マルチワイド文字列「result」だとうまくいきませんでした。
って書いてるけど, 「うまくいった」かどうかはあなたにしか分かりません. なので, これだけでは「理由」を判断しようがありません.
・あなたが期待した結果
・実際に得られた結果
を書いてください.

この回答への補足

回答ありがとうございます。

mallocの部分を以下のように修正しました。
「ans」に読み込む文字列よりも十分に大きいメモリを確保するようにwchar_t型×128文字分確保しました。実際に「ans」に読み込むのは8文字分です。
どうでしょうか?
ちなみに関数の下の方で、printf関数を使っている部分は「ans」と「result」の内容が正しく表示されています。

char mid(wchar_t *str, int st, int ed, char result[128])
{
wchar_t *ans;
ans= (wchar_t*)malloc(sizeof(wchar_t)*128);
if(ans == NULL) printf("con't locate ans \n");
else printf("locate ans O.K. \n");

wcscpy(ans,&str[st]);
ans[ed-st+1] = L'\0';
printf("ans = %ls \n",ans);
wcstombs(result, ans, 128);
printf("result = %s \n",result);

free (ans);
return 0;
}

また、「ans」と「result」の問題は関数から返すときのミスで、修正できました。ありがとうございました。

補足日時:2009/01/09 20:46
    • good
    • 1

質問に対する直接の回答は既に出てるので割愛。



> また、何故かワイド文字列で定義した「ans」のままではうまくいかず、マルチワイド文字列「result」だとうまくいきませんでした。

「ワイド文字列のansではNG、マルチ『バイト』文字列のresultではOK」という意味なら、ワイドかマルチバイトかの差ではなくresultは一定の領域を確保済みだからです。
128バイトを超えれば同じようにエラー停止します。

この回答への補足

回答ありがとうございます。

失礼しました。「マルチバイト文字列」の間違いでした。

補足日時:2009/01/09 12:17
    • good
    • 0

確保量が sizeof(wchar_t) で一文字分しか確保してない


wcscpyで素敵にバッファオーバーフロー
    • good
    • 0

#2さんの回答どおりかと。



>wchar_t *ans = (wchar_t*)malloc(sizeof(wchar_t));

wchar_t型1つ分のメモリしか確保していません。
よって、ワイド型の「文字」しか格納できる分しかありません。
が、
>wcscpy(ans,&str[st]);
「文字列」を入れました。
&str[st]にあるのがが終端コードで無い限り、2文字分以上は書き込まれています。
ということで、Cランタイムが管理しているメモリブロックの管理領域などを破壊したのでしょう。
free()でその破壊された管理領域を参照して次の管理領域をたどって……
あれれれ?
ということかと。
    • good
    • 0

そもそも、



>メモリを解放する段階(free関数の部分)で動作が止まってしまいます。

このことをどうやって確認されましたか?>質問者さん

この回答への補足

回答ありがとうございます。

直前の
wcstombs(result, ans, 128);
printf("result = %s \n",result);
という部分まで表示されて動作が止まることから、そこまでは問題無いかと考えたのですが・・・。

皆さんの言われるように、メモリを確保してみたのですが、うまくいかず悩んでいます。何か他に原因など考えられるでしょうか?

補足日時:2009/01/09 12:12
    • good
    • 0

>free(ans);


>ans = NULL;

これ自体は、問題ありません。
    • good
    • 0

>free(ans);


>ans = NULL;
解放したのに使ってるからじゃない?
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!