C ++ 표준이 파일을 처리하는 방식을 찾는 이유는 무엇입니까?


17

C ++는 streamoff형식을 사용하여 (파일) 스트림 내의 오프셋을 나타내며 [stream.types]에 다음과 같이 정의됩니다.

using streamoff = implementation-defined ;

type streamoff는 운영 체제에 가능한 최대 파일 크기를 나타내기에 충분한 크기의 서명 된 기본 정수 유형 중 하나와 동의어입니다. 287)

287) 일반적으로 길다.

이것은 long32 비트 너비 의을 사용하는 것과는 반대로 큰 파일 내에서 탐색 할 수 있기 때문에 의미 가 있습니다.

[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_typestreamoff[iostreams.limits.pos]를 참조하십시오. 그러나 표준은 함수의 효과를 설명하기 위해 계속됩니다. 나는 마지막 문장에 짜증이 나서 다음을 호출해야합니다 fseek.

효과 : width표시 하자 a_codecvt.encoding(). 경우 is_open() == false, 또는 off != 0 && width <= 0, 그 위치 결정 작업이 실패. 그렇지 않은 경우 way != basic_ios::cur또는 또는 off != 0마지막 작업이 출력 된 경우 출력 시퀀스를 업데이트하고 언 시프트 시퀀스를 작성하십시오. 다음으로 새로운 위치를 찾으십시오 : if width > 0, call fseek(file, width * off, whence), 그렇지 않으면 call fseek(file, 0, whence).

fseeklong매개 변수를 승인합니다 . 경우 off_typestreamoff같이 정의된다 long long(표준에 의해 제안),이에 다운 변환으로 이어질 수 long호출 할 때 fseek(file, width * off, whence)(버그를 진단 할 가능성이 하드로 이어지는). 이것은 처음에 streamoff유형 을 소개하는 전체 이론적 근거에 의문을 제기합니다 .

이것이 표준에 의도적이거나 결함입니까?


8
결함이 생겼습니다.
Yakk-Adam Nevraumont

나는 gcc libstdc ++가 fseeko64를 사용하는 것을 본다고 생각한다 .
KamilCuk

1
실제로, 그것은 후드 아래에서 seekoff반드시 사용 fseek 되는 것처럼 보이지 않습니다 . 오히려 (아마도 친숙한) 행동은 fseek무엇 seekoff을하고 있는지 설명하는 데 사용됩니다 .
jjramsey 2014

@jjramsey 이것도 저의 인상이었습니다. 그러나 그것이 표현되는 방식은 설명보다는 요구 사항을 제안하는 것으로 보인다.
jceed2

1
@jjramsey 본인은 "효과"부분 fseek이 동일한 효과를 가진 무언가를하는 한 실제로 호출 할 필요가 없다는 것을 의미하는 것으로 합리적으로 해석 될 수 있음에 동의합니다 . 그러나 fseek오프셋이 작 LONG_MIN거나 크지 LONG_MAX않은 경우 효과가 없으므로 적어도 streamoff보다 넓은 구현에서는 설명이 불완전 long합니다.
키이스 톰슨

답변:


6

이것에서 C ++ 스트림간에 불일치가 있고 fseek런타임 버그로 이어질 것이라는 결론은 부정확 하다고 생각합니다 . 상황은 다음과 같습니다.

  1. 여기서 시스템은 long64 비트 인 streamoff것으로 정의되는 long, 상기 seekoff기능은 원용 fseek.

  2. 시스템 여기서 long32 비트이지만 OS 지원 64 비트 파일 오프셋이다 streamoff으로 정의 long long하고 seekoff하나라는 함수를 호출 fseeko하거나 fseeko64하는 64 비트 오프셋을 받아 들인다.

다음은 seekoffLinux 시스템 정의의 스 니펫입니다 .

#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는 대용량 파일 지원을 나타냅니다 .

결론 : 표준은 호출 streamoff요구 사항과 명백히 상충 되는 정의가 제안되지만 라이브러리 설계자 는 OS가 지원하는 모든 범위의 오프셋을 허용하는 변형을 호출해야한다는 것을 이해 합니다.seekofffseekfseek


@ypnos 나는 downvote하지 않았고이 답변이 유용하다는 것을 알았습니다. 요점을 놓쳐서 누군가가 공감했다고 생각합니다. 문제는 이와 관련하여 표준을 무시하는 제정신 구현이 없다는 것이 아니라 문제는 구현을 제정하기 위해 표준을 무시해야한다는 것입니다.
jceed2

6
The situation seems to be:-상황은 구현이 호출되지 않도록하는 것 fseek입니다 seekoff. 그것은 호출해야합니다 fseek그렇지 않습니다, 표준 이에있다 말한다. 이 구현이 잘못되었다고 주장 할 수 있습니다. 나는 그것이 질문에 대답하지 않는다고 생각합니다. 루시 발견 LLVM , 그것은 호출합니다 fseeko.
KamilCuk

참고로 VC ++는 _fseeki64이 함수를 요구 합니다. 또한 표준이 말하는 것을 위반하는 것 같습니다.
ChrisMM

1
구현자가 문제를 깨닫고 표준을 무시하는 경우입니다. 나는 그들이 기뻤지 만 표준은 실제로 수정되어야한다.
NathanOliver

1
어떤 사람들은 말 그대로 표준을 받아들이고 있습니다. 구현이 문자 적으로라는 함수를 호출하도록 요구하지는 않습니다 fseek. 다른 곳에서는이 표준이 무언가를 "호출하는 것처럼"설명합니다 fseek(...). 문자 그대로 호출하는 것에 너무 신경 쓰면 fseek그 진술은 다를 것입니다. C ++ 라이브러리를 구현하고 있다면 무엇을 하시겠습니까? fseek문서가 지시하기 때문에 64 비트 파일 오프셋의 하위 32 비트로 호출 할 것을 주장 하시겠습니까 ? 당신의 고객이 그것에 대해 감사합니까?
Willis Blackburn
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.