C ++ używa tego streamoff
typu do reprezentowania przesunięcia w strumieniu (pliku) i jest zdefiniowany w następujący sposób w [stream.types]:
using streamoff = implementation-defined ;
Typ streamoff jest synonimem jednego z podpisanych podstawowych integralnych typów o wystarczającym rozmiarze, aby reprezentować maksymalny możliwy rozmiar pliku dla systemu operacyjnego. 287)
287) Zazwyczaj długi.
Ma to sens, ponieważ pozwala na wyszukiwanie w dużych plikach (w przeciwieństwie do używania long
, które może mieć tylko 32 bity szerokości).
[filebuf.virtuals] definiuje basic_filebuf
funkcję wyszukiwania w pliku w następujący sposób:
pos_type seekoff(off_type off, ios_base::seekdir way, ios_base::openmode which = ios_base::in | ios_base::out) override;
off_type
jest równoważne streamoff
, patrz [iostreams.limits.pos]. Jednak standard wyjaśnia dalej efekty tej funkcji. Denerwuje mnie ostatnie zdanie, które wymaga połączenia z fseek
:
Efekty : Niech
width
oznacza_codecvt.encoding()
. Jeśliis_open() == false
luboff != 0 && width <= 0
, operacja pozycjonowania kończy się niepowodzeniem. W przeciwnym razie, jeśliway != basic_ios::cur
luboff != 0
, i jeśli została wykonana ostatnia operacja, zaktualizuj sekwencję wyjściową i zapisz dowolną sekwencję cofania. Następnie szukaj nowej pozycji: jeśliwidth > 0
zadzwońfseek(file, width * off, whence)
, w przeciwnym razie zadzwońfseek(file, 0, whence)
.
fseek
akceptuje long
parametr. Jeśli off_type
i streamoff
są zdefiniowane jako long long
(jak sugeruje standard), może to prowadzić do obniżenia konwersji do long
podczas wywoływania fseek(file, width * off, whence)
(prowadząc do potencjalnie trudnych do zdiagnozowania błędów). To podważa całe uzasadnienie wprowadzenia tego streamoff
typu w pierwszej kolejności.
Czy jest to celowe czy wada normy?
seekoff
konieczność użyciafseek
pod maską. Raczej (przypuszczalnie znajome?) Zachowaniefseek
służy raczej do wyjaśnienia, coseekoff
się dzieje.fseek
o ile robi coś z tym samym efektem. Alefseek
z przesunięciem mniejszymLONG_MIN
lub większym niżLONG_MAX
nie ma żadnego efektu, więc wyjaśnienie jest w najlepszym razie niekompletne, przynajmniej w przypadku wdrożeń, którestreamoff
są szersze niżlong
.Odpowiedzi:
Myślę, że wniosek, z którego czerpiesz, że istnieje rozbieżność między strumieniami C ++ i
fseek
który doprowadzi do błędów w środowisku wykonawczym, jest błędny. Sytuacja wydaje się następująca:W systemach, w których
long
jest 64 bity,streamoff
jest zdefiniowany jakolong
iseekoff
funkcja jest wywoływanafseek
.W systemach, gdzie
long
wynosi 32 bity, ale obsługuje 64-bitowe OS offsety w pliku,streamoff
jest zdefiniowane jakolong long
iseekoff
wywołuje funkcję o nazwie albofseeko
albofseeko64
że akceptuje 64-bitowy offset.Oto fragment kodu z definicji
seekoff
w moim systemie Linux:LFS oznacza obsługę dużych plików .
Wniosek: Chociaż standard sugeruje definicję
streamoff
tego rzekomo sprzecznego z wymaganiem, które należyseekoff
wywołaćfseek
, projektanci bibliotek rozumieją, że muszą nazwać wariant tego,fseek
który akceptuje pełny zakres przesunięć obsługiwanych przez system operacyjny.źródło
The situation seems to be:
- Sytuacja jest taka, że realizacja nie może nie wywołaćfseek
wseekoff
. Musi zadzwonićfseek
, nie ma, standard mówi, że musi. Mogę argumentować, że ta implementacja jest nieprawidłowa. Uważam, że to nie odpowiada na pytanie. Och, znalazłem lvvm , wołafseeko
._fseeki64
tę funkcję; co również wydaje się naruszać to, co mówi standard.fseek
. Gdzie indziej standard opisuje coś jako „jakby przez telefonfseek(...)
”. Gdyby tak bardzo mu zależało na dosłownym dzwonieniufseek
, to stwierdzenie byłoby inne. Poważnie, co byś zrobił, gdybyś implementował bibliotekę C ++? Czy nalegałbyś na wywołaniefseek
przy użyciu niższych 32 bitów 64-bitowego przesunięcia pliku, ponieważ dokument tak mówi? Czy Twoi klienci ci za to podziękują?