Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

freadのエラーの理由

3,955 views
Skip to first unread message

makoto

unread,
Oct 11, 2001, 10:18:41 AM10/11/01
to
freadを使っているとファイルの終わりじゃなくても0を返す
ときがあります。EOFがくる以外にfreadが終了するときはどんな時なんで
しょうか?ちなみに使っているのはBcc32です。

Takeshi SHIGIHARA

unread,
Oct 11, 2001, 10:47:41 AM10/11/01
to

BCC32ということは、環境はWindowsかなぁ。
MS-DOSの流れで、ファイル中に 0x1A というコードがあると、それをEOFと
見なす場合も考えられます。 fopen時に「テキストモード」で開いている
場合に、そのような制御が行われる場合が考えられます。

それ以外には、読み出すサイズや最大個数に0を指定したとか、読み出し中に
何らかのエラーが起こったとか。

feof とか ferror で調べてみましたか?


---- Takeshi SHIGIHARA
OFFICE cyg...@zero.ad.jp
HOME cyg...@po.jah.ne.jp , cyg...@tka.att.ne.jp ------------

makoto

unread,
Oct 11, 2001, 1:02:48 PM10/11/01
to

>> freadを使っているとファイルの終わりじゃなくても0を返す
>> ときがあります。EOFがくる以外にfreadが終了するときはどんな時なんで
>> しょうか?ちなみに使っているのはBcc32です。
>
環境はWindowsです。

>MS-DOSの流れで、ファイル中に 0x1A というコードがあると、それをEOFと
>見なす場合も考えられます。 fopen時に「テキストモード」で開いている
>場合に、そのような制御が行われる場合が考えられます。
また"rb"で読み出しています

>それ以外には、読み出すサイズや最大個数に0を指定したとか、読み出し中に
>何らかのエラーが起こったとか。
>
>feof とか ferror で調べてみましたか?
feofとかferrorとかclearerrとか役に立つんでしょうか?
結局fopen(**,"rb")の時に呼び出したとき失敗したら
そのファイルは「無い」と判断させてますし、
バイナリモードで読み出しならfreadが0を返すときはEOFと判断させてます。
(読み出しサイズや最大数は考慮に入れてます。)
どんなエラーか?というのは判断できないし。

Junn Ohta

unread,
Oct 11, 2001, 9:24:25 PM10/11/01
to
fj.comp.lang.cの記事<3bc5aa2b.7057%mak...@o-gata.net>で
mak...@o-gata.netさんは書きました。
> freadを使っているとファイルの終わりじゃなくても0を返す
> ときがあります。EOFがくる以外にfreadが終了するときはどんな時なんで
> しょうか?

0を返すかどうかはともかく、たいていの場合は終了す
ると思いますが...。:-)

> ちなみに使っているのはBcc32です。

intは何バイトですか?

intが2バイトなら、size_tの値が返ってくるのにintで
受けていたりすると、65536の倍数が返ってきたときに
0が返ってきたように見えるかもしれませんね。
--
太田純(Junn Ohta) (株)リコー/新横浜事業所
oh...@sdg.mdd.ricoh.co.jp

Takeshi SHIGIHARA

unread,
Oct 11, 2001, 10:12:43 PM10/11/01
to
makoto wrote:
> 結局fopen(**,"rb")の時に呼び出したとき失敗したら
> そのファイルは「無い」と判断させてますし、

環境によりますが、ファイルがあっても読み出しを許可されていない場合と
いうのも考えられます。いずれにしても読めないわけで、実質、無いとも
言えますが。

COMポートとかを開けているのなら、タイムアウトを起こしたなどで、
freadから0が返ることも考えられないわけじゃないですが、
ファイルはディスク上のファイルですよね……
他のプロセスにより、ファイルの途中をLockされていたとか?

freadが読み出したデータを書き込む領域が、何らかの理由で重要なメモリ
を誤って破壊してしまったために動作がおかしくなったとか?


うーむ、申し訳ないけれど、私ごときではお手上げです。

----- Takeshi SHIGIHARA
Office cyg...@zero.ad.jp
Home cyg...@po.jah.ne.jp -----

Shinobu Kumaoka

unread,
Oct 11, 2001, 10:10:27 PM10/11/01
to
熊岡です。

makoto wrote:

プロセス間の情報のやりとりにファイルを使っている場合には、
ファイルの終端でなくても、0が返る時があります。

あと、デバイスが遅い場合、例えばネットワーク経由の時にもありえるのかな。

--
cog...@sp.hudson.co.jp
株式会社ハドソン
研究開発本部 研究開発課
熊岡 忍(Kumaoka Shinobu)


Iwao Watanabe

unread,
Oct 11, 2001, 9:37:27 PM10/11/01
to
"makoto" <mak...@o-gata.net> wrote
in message news:3bc5d0a3.7058%mak...@o-gata.net...

> feofとかferrorとかclearerrとか役に立つんでしょうか?
(snip)
> (読み出しサイズや最大数は考慮に入れてます。)
> どんなエラーか?というのは判断できないし。
>

ferror が真を返してきたら、errno にその理由が記録されているので
strerrorで処理系が用意しているメッセージを取り出して
利用者にそれを見せるくらいはしてもよいのではないでしょうか。

私はそうしています。

feof は確かにfreadと合わせて使いませんが,

int value; FILE *fp;

while ((value = getw(fp)) != EOF || !feof(fp))
printf("%d ",value);

みたいな場面で使います。

getwは処理系によっては無いかもしれません。
いまFreeBSDとSunOSで確認しました。

getcはEOFと比較するだけで十分ですが,
getwはEOFと重なるコードを返すかもしれないので
feofとあわせてテストします。

makoto

unread,
Oct 13, 2001, 10:01:20 AM10/13/01
to
原因は最大数を大きくとりすぎているためでした
(大きいってほどでも無いと思うのですが)
size_t fread(void *ptr, size_t size, size_t n, FILE *stream);
でn=8で設定していたらだめでn=1にして繰り返させたらうまくいきました。
(2でもOKで3だとだめでした)
ですけどsize=256でハードディスク上にあるファイルなのに
2048byteくらい一気に読めないんでしょうか・・・

ちなみに環境はwindows98で
bcc32(Borland C++ Compiler 5.5)です。
sizeof(int)=4;です

Ichi

unread,
Oct 13, 2001, 1:40:52 PM10/13/01
to
makoto wrote in message
<3bc83870.7059%mak...@o-gata.net>:

> size_t fread(void *ptr, size_t size, size_t n, FILE *stream);
> でn=8で設定していたらだめでn=1にして繰り返させたらうまくいきました。
> (2でもOKで3だとだめでした)
> ですけどsize=256で
freadは「sizeバイト単位で」データを読み込み、
完全に読みこめたsizeバイトのかたまりの個数を返します。
例えば、size=256で、実際に読みこんだバイト数が256バイト未満
(つまり、ファイル終端まで256バイトなかった)だと、
戻り値が0になります。

ファイルに何バイト単位でデータが格納されているのか
分からない時に、2048バイトずつ読みたいのなら、
fread(buf, 1, 2048, fp);
とすればOKです。


例(712バイトのファイルの場合)

char buf[256];
FILE *fp;
fp = fopen(...);

/* ファイルから256バイト読みこまれる。戻り値は1 */
fread(buf, 256, 1, fp);


/* ファイルから256バイト読みこまれる。戻り値は1 */
fread(buf, 256, 1, fp);

/* ファイルから200バイト読みこまれるが、これは256より
小さい、つまりかたまり一個分に満たないので、戻り値は0 */
fread(buf, 256, 1, fp);

--
Ichi
ic...@mizar.freemail.ne.jp

電子のお針箱

unread,
Oct 13, 2001, 9:08:11 PM10/13/01
to
makoto <mak...@o-gata.net> wrote in message
news:3bc83870.7059%mak...@o-gata.net...

> 原因は最大数を大きくとりすぎているためでした
> (大きいってほどでも無いと思うのですが)
> size_t fread(void *ptr, size_t size, size_t n, FILE *stream);
> でn=8で設定していたらだめでn=1にして繰り返させたらうまくいきました。
> (2でもOKで3だとだめでした)

まさかとは思いますが、*ptr が指す領域は 2048 バイト確保されているん
ですよね ?

--
---------------
電子のお針箱
ue...@di.mbn.or.jp
---------------

makoto

unread,
Oct 13, 2001, 10:27:15 PM10/13/01
to

>/* ファイルから200バイト読みこまれるが、これは256より
>小さい、つまりかたまり一個分に満たないので、戻り値は0 */
>fread(buf, 256, 1, fp);
>
つまり戻り値が0でも読み込みは正常に動作しているということですね。
勉強になります。

電子のお針箱さんの<9qap44$72l$3...@newsjp.mbn.or.jp>から


>まさかとは思いますが、*ptr が指す領域は 2048 バイト確保されているん
>ですよね ?

そこまであほじゃないつもりです。といいたいのですが・・・

なんだかんだいって作り直したら
ちゃんと一気に2048byte読めてしまいました。
ということはなにが原因なのか。
typedef struct
{
unsigned char type[16]; /*ジャンル名*/
short pass;
short size; /*問題数*/
short skip; /*アクセスのため*/
unsigned char file[12]; /*セーブデータファイル名*/
unsigned char code[8]; /*gotakuデータ確認用*/
unsigned char fill[214];
}head;

head data[8];
と確保していたものを
ptr=data;
としたと思います。うーん消すんじゃなかった
今度はあのときのエラーが再現できないや。

ちなみに*ptrの指すポインタが2048バイトで無かったら
エラーにというかバグると思うんですけど
freadってptrの指すポインタのサイズが足りないと0を返すんですか?

とりあえずうまく動作しました。ありがとうございました。

Masao Seki

unread,
Oct 14, 2001, 12:39:48 AM10/14/01
to
関@神奈川と申します。

makoto wrote in: <3bc8f7f5.7060%mak...@o-gata.net>


>
> >/* ファイルから200バイト読みこまれるが、これは256より
> >小さい、つまりかたまり一個分に満たないので、戻り値は0 */
> >fread(buf, 256, 1, fp);
> >
> つまり戻り値が0でも読み込みは正常に動作しているということですね。

少し違うと思います。

戻り値が0は、コーディングの意図がどうあろうと、異常終了を表します。
例え、EOFを期待した所で0が返って来た場合でも、ferror()に引っかかる
何らかの異常が無かったと云う保証はありません。
# ついでに言えば、EOFの判定には、feof()を用いるのが本筋だと思います。

freadで、或る固まり単位で読んでいる時、固まり単位の読みが成功したか
どうかだけに興味がある時は、sizeの方に固まりのサイズを、nの方に読み
たい固まりの個数を入れます。

それに対して、指定した読み込みバイト数の読み込みに失敗する事が予め
予想されており、失敗した時、何バイト読み込んでいたのかの情報が欲し
い時は、size=1にして、nには一回に読み込みたい総バイト数を入れます。

いずれにしても、
fread()からの返り値 != n
は、読み込みの失敗を表していますからfeof(),ferror()のチェックをして
から、先の処理に進むべきでしょう。


> ちなみに*ptrの指すポインタが2048バイトで無かったら
> エラーにというかバグると思うんですけど
> freadってptrの指すポインタのサイズが足りないと0を返すんですか?

正確に言うと、「ptrの指すポインタ(アドレス)を先頭にして確保され
ている領域サイズが」ですね。
偶然、0を返す事もあるかも知れませんが、C言語ではその手のチェック
は行われません。

この場合は、予期出来ないエラーが発生するのが普通で、この手の不具合
が原因で発生するエラーは、エラーメッセージさえまともに信じてはいけ
なくなる程、たちの悪いものです。
一見正常終了していて、(実際、表には一切の不具合も現れない事も在り
ますが)、結果の数値だけ間違っていたり、実行時のデータや実行環境が
変った時に、問題が顕在化する事もあります。

--
関@神奈川
Masao Seki <ma-...@gb3.so-net.ne.jp>

電子のお針箱

unread,
Oct 14, 2001, 8:50:50 AM10/14/01
to
makoto <mak...@o-gata.net> wrote in message
news:3bc8f7f5.7060%mak...@o-gata.net...

> 電子のお針箱さんの<9qap44$72l$3...@newsjp.mbn.or.jp>から
> >まさかとは思いますが、*ptr が指す領域は 2048 バイト確保されているん
> >ですよね ?
> そこまであほじゃないつもりです。といいたいのですが・・・

まあそうですよね。一応念のために...、という意味で書きました。

# 「確保はちゃんとしてるけど、ptr が全然違うところを指していた」なんて
# こともありますから...。(ひょっとして、私だけ ?)

> ちなみに*ptrの指すポインタが2048バイトで無かったら
> エラーにというかバグると思うんですけど

領域を超えてデータを書かれるわけですから、何が起こっても不思議は無い
です。少なくとも...

> freadってptrの指すポインタのサイズが足りないと0を返すんですか?

等と言う、便利な (≒ おせっかいな) 機能は普通の処理系にはありません。

0 new messages