web-dev-qa-db-ja.com

C ++標準がファイルを処理する方法を模索するのはなぜですか?

C++はstreamoffタイプを使用して(ファイル)ストリーム内のオフセットを表し、[stream.types]で次のように定義されます。

_using streamoff = implementation-defined ;_

タイプstreamoffは、オペレーティングシステムの最大可能ファイルサイズを表すのに十分なサイズの、署名された基本的な整数型の1つの同義語です。 287)

287)通常は長いです。

longを使用するのとは対照的に、32ビット幅しかない可能性があります)大きなファイル内でシークできるため、これは理にかなっています。

[filebuf.virtuals]は、ファイル内をシークする_basic_filebuf_関数を次のように定義します。

pos_type seekoff(off_type off, ios_base::seekdir way, ios_base::openmode which = ios_base::in | ios_base::out) override;

_off_type_はstreamoffと同等です。[iostreams.limits.pos]を参照してください。ただし、標準は関数の影響を説明します。 fseekの呼び出しを必要とする最後の文にイライラします。

効果widtha_codecvt.encoding()を示します。 is_open() == false、または_off != 0 && width <= 0_の場合、位置決め操作は失敗します。それ以外の場合、_way != basic_ios::cur_または_off != 0_の場合、および最後の操作が出力された場合は、出力シーケンスを更新して、シフトなしのシーケンスを書き込みます。次に、新しい位置を探します。_width > 0_の場合はfseek(file, width * off, whence)を呼び出し、それ以外の場合はfseek(file, 0, whence)を呼び出します。

fseeklongパラメータを受け入れます。 _off_type_およびstreamoffが_long long_として定義されている場合(標準で推奨)、これによりfseek(file, width * off, whence)を呼び出すときにlongへのダウンコンバージョンが発生する可能性があります(バグを診断するのは難しい)。これは、最初にstreamoff型を導入する根拠全体に疑問を投げかけます。

これは意図的なものですか、それとも規格の欠陥ですか?

17
jceed2

あなたがこれから引き出されている、C++ストリームとfseekの間にランタイムバグにつながる不一致があるという結論は正しくないと思います。状況は次のようです:

  1. longが64ビットのシステムでは、streamofflongとして定義され、seekoff関数はfseekを呼び出します。

  2. longが32ビットであるがOSが64ビットのファイルオフセットをサポートするシステムでは、streamofflong longとして定義され、seekofffseekoまたはfseeko64は64ビットのオフセットを受け入れます。

Linuxシステムでのseekoffの定義からのスニペットは次のとおりです。

#ifdef _GLIBCXX_USE_LFS
    if (!fseeko64(_M_file, __off, __whence))
      __ret = std::streampos(ftello64(_M_file));
#else
    if (!fseek(_M_file, __off, __whence))
      __ret = std::streampos(std::ftell(_M_file));
#endif

LFSは Large File Support の略です。

結論:標準はstreamoffの定義がseekofffseekを呼び出す要件と表面的に矛盾することを提案している一方で、ライブラリ設計者はfseekこれは、OSがサポートするオフセットの全範囲を受け入れます。

6