C言語関係掲示板

過去ログ

No.1349 mallocでの領域確保の際に生じるズレ

[戻る] [ホームページ]
No.18371

mallocでの領域確保の際に生じるズレ
投稿者---ふい(2004/11/25 11:55:21)


はじめまして。
前にJavaをやっていたものの、まだC始めて2週間ぐらいなのでポインタ・メモリ等の理解に苦しんでいます。
下記のようなプログラムの一部をテストしていたのですが、色々数値を変えたりして試していたもののどうもうまくいきません。
コンパイラはVC++6.0です。
軽いヒントだけでも十分ですので、是非助言よろしくお願いします。

ちなみに目的はファイルの内容のメモリへの展開・別ファイルへのコピーです。
適当にキーボード打った内容が入ったa.txtを同フォルダにいれてます。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

/*********************
    Test用cppファイル
**********************/
int main()
{
    //読み込み・書き出し用文字列ポインタ
    char *moji;

    //読み込み元・書き込み先ファイルポインタ
    FILE *a = fopen("a.txt","r");
    FILE *b = fopen("b.txt","w");
    
    //ファイルのサイズの確認
    fseek(a,0L,SEEK_END);
    int quo=(ftell(a)+1);
    printf("quoのメモリ領域:%d\n",quo);

    //quo分のメモリ割り当て(ランダムなファイルの大きさに対応)
    moji = (char *)malloc(quo);

    //ファイルのコピー
    rewind(a);
    fread(moji,sizeof(char),quo,a);
    fwrite(moji,sizeof(char),quo,b);

    //数値がquoと合わない(計り方がオカシイ・・・?)
    printf("コピー後のmojiの文字列長%d\n",strlen(moji));

    //確認のためmojiの内容表示。語尾に文字化けが現れる(output先のファイルにも。)
    puts(moji);
    
    //終了
    fclose(a);
    fclose(b);
    free(moji);

    return 0;
}



No.18373

Re:mallocでの領域確保の際に生じるズレ
投稿者---nop(2004/11/25 12:34:21)


>fread(moji,sizeof(char),quo,a);
>printf("コピー後のmojiの文字列長%d\n",strlen(moji));

文字列の終端を示す'\0'文字を入れ忘れているためでしょう。


No.18375

Re:mallocでの領域確保の際に生じるズレ
投稿者---朱鷺(2004/11/25 12:50:01)


文字化けがおきるのはおそらく初期化してないことが原因。
mojiを初期化してみてください。
bはどこで使ってるんですか?
開いて閉じてるだけのような気が・・・
ファイルを開くときにバイナリモードにするとどうなりますか?





No.18376

Re:mallocでの領域確保の際に生じるズレ
投稿者---ふい(2004/11/25 13:13:43)


nopさん、朱鷺さんレスありがとうございます。

>nopさん
終端を示す'\0'文字というのは
int quo=(ftell(a)+1);
で確保した分とは別物のことでしょうか?
考えとしては先ず元ファイルのサイズを測り、
そのサイズ+1(終端文字分)を確保した領域をmojiのポイント部に確保。
その後終端文字を含め読み込み元ファイルのコピー。
って感じだったんですが・・・。



>朱鷺さん
NULLで初期化しても変化はありませんでした。。。

/*********こんな感じでテストしてみました*******
    //quo分のメモリ割り当て(ランダムなファイルの大きさに対応)
    moji = (char *)malloc(quo);
    *moji = NULL;

******無理でした…(´・ω・)*************/
また、バイナリモードでも変化がなかったです。
ファイルbはfwriteの部分で使っています(書き込み先ファイル)


一応実行結果を下に示しておきますね。
-a.txt(入力内容)
this is a test file that will be duplicated by C program.
how is it goin'?

-b.txt(実行後)
this is a test file that will be duplicated by C program.
how is it goin'?ヘ

-コンソール(実行後)
quoのメモリ領域:76
コピー後のmojiの文字列長81
this is a test file that will be duplicated by C program.
how is it goin'?ヘ&#63729;&#63729;&#63729;&#63729;ミ
Press any key to continue


quoのメモリ領域とコピー後のmojiの文字列長って変化するのはデフォルトなんでしょうか?
現在はstrcatでmojiに終端文字くっつけたりしてます。
後OS書いてませんでしたがWin2kです。
めげずに頑張ってみます!


No.18377

Re:mallocでの領域確保の際に生じるズレ
投稿者---ふい(2004/11/25 13:15:41)


さ、最後が大変なことに!
すみませんすみません!<コンソール結果部


No.18379

Re:mallocでの領域確保の際に生じるズレ
投稿者---nop(2004/11/25 13:51:23)


>終端を示す'\0'文字というのは
>int quo=(ftell(a)+1);
>で確保した分とは別物のことでしょうか?

確保だけして、'\0'を設定していない、って事。

calloc()で確保するか、
malloc()の後にmemset()で領域を全て0で埋めてみましょう。


No.18380

Re:mallocでの領域確保の際に生じるズレ
投稿者---neet(2004/11/25 13:59:48)


>>nopさん
>終端を示す'\0'文字というのは
>int quo=(ftell(a)+1);
>で確保した分とは別物のことでしょうか?

半角一文字って何byteだっけ?
一応確認してみてください。(私の記憶では2byte)
あと、
int quo = ftell(a)+x;
で、括弧は必要ないかと・・・


No.18382

Re:mallocでの領域確保の際に生じるズレ
投稿者---nop(2004/11/25 14:11:10)


>半角一文字って何byteだっけ?
>一応確認してみてください。(私の記憶では2byte)

1 Byteです。
sizeof(char)は 1 であるのが規格で保証されています。

# char は半角1文字を表現出来るサイズを有する型ですから。
#
## 全角文字であれば多バイトでしょうけどね。


No.18385

Re:mallocでの領域確保の際に生じるズレ
投稿者---Ban(2004/11/25 14:25:14)


>半角一文字って何byteだっけ?

半角文字という表現は微妙だと思いますが、
この場合は 1byte でいいと思います。



No.18386

Re:mallocでの領域確保の際に生じるズレ
投稿者---ふい(2004/11/25 14:32:00)


nopさん、neetさんありがとうございました。
nopさんのやり方(calloc()の方ですね)を試してみたところ出来ました!
やはり朱鷺さんも言っていたように初期化がされてなかったんですね。
//っていうかさっきの私の初期化方法はイッタイドコカラ。

が、疑問が残りました。
なんでmalloc()を使った場合に二つ目の引数で指定した数ピッタリのメモリ領域が確保されなかったのでしょう?
それがとても不思議で・・・。
色々なページのサンプルを見ても全て指定サイズ通り確保できてるように見受けられるのですが・・・。
//それともやっぱり私のサイズの測り方が間違ってたのでしょうか?それでも微妙にあまるあの領域はイッタイ・・・?

とにもかくにもお答えくださった皆様、本当にありがとうございました。
恐らくそのうちまた来ます(笑


No.18387

Re:mallocでの領域確保の際に生じるズレ
投稿者---επιστημη(2004/11/25 14:51:56)


>なんでmalloc()を使った場合に二つ目の引数で指定した数ピッタリのメモリ領域が確保されなかったのでしょう?

マニュアルには以下のように '明記' されておりました。

少なくとも size で指定したバイトのメモリ ブロックを割り当てます。
^^^^^^^^^



No.18388

Re:mallocでの領域確保の際に生じるズレ
投稿者---ふい(2004/11/25 15:05:23)


>επιστημηさん
明記・・・す、すみません、お手数かけました。
でも疑問解消されました!

ありがとうございましたー


No.18389

Re:mallocでの領域確保の際に生じるズレ
投稿者---かずま(2004/11/25 15:28:37)


> nopさんのやり方(calloc()の方ですね)を試してみたところ出来ました!

出来ていないはずです。a.txt と b.txt のファイルのサイズを
dir コマンドで確認してみてください。違っていませんか?

callocを使うと、ゴミの代わりに '\0' が付くので、それが見えないだけです。

正しい修正方法は、fopen("a.txt", "rb") と fopen("b.txt", "wb")

次のCプログラムでうまくいくはずです。
C++ プログラムにしたければ、malloc の前にキャスト (char *) を入れると
コンパイルできますが、C++ なら malloc/free の代わりに new/delete を
使います。
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

int main(void)
{
    char *moji;
    int quo, n;
    FILE *a = fopen("a.txt", "rb");
    FILE *b = fopen("b.txt", "wb");
    
    fseek(a, 0, SEEK_END);
    quo = ftell(a);
    printf("quoのメモリ領域:%d\n", quo + 1);
    moji = malloc(quo + 1);
    rewind(a);
    n = fread(moji, 1, quo, a);
    fwrite(moji, 1, n, b);
    moji[n] = '\0';
    printf("コピー後のmojiの文字列長%d\n", strlen(moji));
    puts(moji);
    fclose(a);
    fclose(b);
    free(moji);
    return 0;
}



No.18390

Re:mallocでの領域確保の際に生じるズレ
投稿者---ふい(2004/11/25 15:55:18)


なんとかNULL文字全部自分で消そうと頑張ってました。(笑
完璧にコピーできました!mallocの際の領域のズレもなし・・・!
なんで!?<さすがに調べマス(笑
ほんとに助かりました。freadの返り値がああいう風に使えるとは思ってませんでした。
標準ライブラリの一覧・具体的な使用方法の載った本でも買う事を決意。

ぱぱーっとこのプログラム書けるぐらいに早くなりたいなぁ、と思います。
かずまさん、ありがとうございました!


No.18391

Re:mallocでの領域確保の際に生じるズレ
投稿者---かずま(2004/11/25 16:05:41)


> 正しい修正方法は、fopen("a.txt", "rb") と fopen("b.txt", "wb")

こう書きましたが、実は fread が返した値 n で fwrite すれば、
fopen は元の通りテキストモードでもたいていうまくいきます。


No.18392

Re:mallocでの領域確保の際に生じるズレ
投稿者---ふい(2004/11/25 16:24:09)


かずまさん、たびたびありがとうございます。

バイナリの方が安定しているんですね。
謎がいっぱい。
でも読み込み・吐き出しの際のキーはfreadの返り値ってことなのかな?

・・・ってバイナリ使う理由書いてるぢゃん・・・!<第17章ファイル入出力
ほ、ほんとすみません。うわー、見過ごしてた・・・。

こ、こんなへたれに丁寧に教えてくれて皆様ありがとうございました!


No.18395

Re:mallocでの領域確保の際に生じるズレ
投稿者---RAPT(2004/11/25 21:38:15)


・テキストモードとバイナリモードとの違いは、改行文字の扱い。
・fread()関数で返される値は、実際に読み出した全項目の数。
この辺のところは、調べれば分かることです。調べてください。