fclose return value check
fclose의 리턴 값을 확인해야 합니까?파일을 성공적으로 연 경우 닫히지 않을 가능성은 얼마나 됩니까?
이 할 때.fwrite파일에 실제로는 아무것도 쓰지 않을 수도 있고 버퍼(FILE 개체 내부)에 남아 있을 수 있습니다. 중인gfflush실제로 디스크에 쓸 수도 있습니다.예를 들어 디스크 공간이 부족하거나 다른 I/O 오류가 있는 경우 이 작업이 실패할 수 있습니다.
fclose버퍼도 암시적으로 플러시하므로 동일한 이유로 실패할 수 있습니다.
fclose() 호출은 실패할 수 있으므로 다른 모든 파일 작업과 마찬가지로 오류를 검사해야 합니다.현학적으로 들리죠?틀렸어.전생에 우리 회사 제품은 파일을 닫을 때 장애 확인을 생략하여 고객의 데이터를 파기할 수 있었습니다.순서는 다음과 같이 진행되었습니다.
stream = fopen(tempfile, "w"); if (stream == NULL) ... while (more_to_write) if (fwrite(buffer, 1, buflen, stream) != buflen) ... fclose (stream); /* The new version has been written successfully. Delete * the old one and rename. */ remove (realfile); rename (tempfile, realfile);물론, fclose()가 마지막 몇 블록의 데이터를 쓰려다 디스크 공간이 부족하여 'tempfile'이 잘려서 사용할 수 없게 되었습니다.그리고 fclose() 실패가 감지되지 않았기 때문에 프로그램은 바로 진행하여 현존하는 가장 좋은 버전의 데이터를 파괴하고 손상된 버전을 선호했습니다.머피가 알 수 있듯이, 이 사건의 피해자는 고객 부서의 책임자, 우리 제품을 더 사거나 경쟁사 제품으로 교체할 권한을 가진 사람, 그리고 이미 다른 이유로 우리에게 불만을 품은 사람이었습니다.
그 후의 모든 불행을 이 하나의 누락 탓으로 돌리는 것은 무리가 있겠지만, 그 이후로 고객과 이전 회사 모두 기업 생태계에서 사라졌다는 점을 지적할 필요가 있을 것입니다.
그 고장 코드들을 확인하세요!
오류를 보고할 수도 있고, 보고해야 하지만 어떤 의미에서는 스트림이 여전히 닫혀 있습니다.
fclose()로 호출한 후 스트림을 사용하면 정의되지 않은 동작이 발생합니다.
fclose()다를 통해fflush()) 를에서 오류가 합니다.write()에 보고되지 않을 것입니다fwrite()아니면fprintf()을 할 때.fclose()으로,write()아니면fflush()다에 될 수 있습니다.fclose().fclose()또한 전화할 것입니다.close()할 수 다 전에는 변경된 파일은 다음까지 원격 서버에 업로드되지 않습니다.close(). NFS되면,close()이고,fclose()역시 실패할 것입니다.이는 다른 네트워크 파일 시스템의 경우에도 해당될 수 있습니다.
fclose()의 결과를 항상 확인해야 합니다.
데이터를 생성하고 있다고 가정해 보겠습니다.당신은 당신이 가지고 있는 오래된 데이터를 가지고 있습니다.fread()파일에서 데이터를 처리하고 더 많은 데이터를 생성한 다음 새 파일에 씁니다.새 파일을 만들려는 시도가 실패할 수 있으므로 이전 파일을 덮어쓰지 않도록 주의해야 하며, 그런 경우에는 이전 데이터를 보관해야 합니다(일부 데이터는 데이터가 없는 것보다 낫습니다).에를 후에.fwrite(), 합니다(에)에서을 꼼꼼하게 에)fwrite()), fclose()서류철그럼 당신은rename()방금 작성한 파일과 이전 파일을 덮어씁니다.
한다면fclose()쓰기 오류(디스크가 가득 찼다고요?) 때문에 실패했습니다. 마지막 정상 파일을 정크 파일로 덮어씁니다.라.
의 .fclose().
코드 측면:
#include <stdio.h>
#include <stdlib.h>
int main(void)
{
FILE *ifp = fopen("in.dat", "rb");
FILE *ofp = fopen("out.dat", "wb");
char buf[BUFSIZ];
size_t n;
int success = 1;
if (ifp == NULL) {
fprintf(stderr, "error opening in.dat\n");
perror("in.dat");
return EXIT_FAILURE;
}
if (ofp == NULL) {
fclose(ifp);
fprintf(stderr, "error opening out.dat\n");
perror("out.dat");
return EXIT_FAILURE;
}
while ((n = fread(buf, 1, sizeof buf, ifp)) > 0) {
size_t nw;
if ((nw = fwrite(buf, 1, n, ofp)) != n) {
fprintf(stderr, "error writing, wrote %lu bytes instead of %lu\n",
(unsigned long)n,
(unsigned long)nw);
fclose(ifp);
fclose(ofp);
return EXIT_FAILURE;
}
}
if (ferror(ifp)) {
fprintf(stderr, "ferror on ifp\n");
fclose(ofp);
fclose(ifp);
return EXIT_FAILURE;
}
#ifdef MAYLOSE_DATA
fclose(ofp);
fclose(ifp);
rename("out.dat", "in.dat"); /* Oops, may lose data */
#else
if (fclose(ofp) == EOF) {
perror("out.dat");
success = 0;
}
if (fclose(ifp) == EOF) {
perror("in.dat");
success = 0;
}
if (success) {
rename("out.dat", "in.dat"); /* Good */
}
#endif
return EXIT_SUCCESS;
}
에 를 기울여 .fopen(),fwrite(),그리고.fread()안 요, 도, fclose()가 손실될 수 다우)로 ).MAYLOSE_DATA정의됨).
fclose가 실패할 수 있는 한 가지 이유는 여전히 버퍼링된 데이터가 있고 암시적 fflush가 실패하는 경우입니다.제가 추천하는 것은 항상 fflush를 호출하고 오류 처리를 하는 것입니다.
저는 fclose()가 0이 아닌 상태로 돌아오는 것을 여러 번 보았습니다.
그리고 신중하게 검토한 결과 실제 문제는 근접한 것이 아니라 쓰기에 있다는 것을 알게 되었습니다.
작성 중인 내용이 실제 쓰기 전에 버퍼링되고 fclose()가 호출되면 모든 버퍼가 플러시됩니다.따라서 fclose() 중에 디스크가 꽉 차 있는 것과 같이 버퍼를 작성하는 데 문제가 발생합니다.David Yell이 말했듯이 방탄 애플리케이션을 작성하려면 fclose()의 반환 값을 고려해야 합니다.
fclose man 페이지는 close 또는 fflush가 실패할 수 있는 이유 중 하나로 실패할 수 있다고 언급합니다.
인용:
시스템 닫기 호출은 다음과 같은 경우 실패합니다.
[EBADF] fildes is not a valid, active file descriptor. [EINTR] Its execution was interrupted by a signal. [EIO] A previously-uncommitted write(2) encountered an input/output error.
fflush는 기본적으로 파일에 실제로 쓰기/저장할 수 없는 경우에 쓰기 ()이 실패할 수 있는 이유로 실패할 수 있습니다.
어떤 의미에서 파일을 닫는 것은 절대 실패하지 않습니다. 보류 중인 쓰기 작업이 실패하면 오류가 반환되지만 스트림은 닫힙니다.
문제를 방지하고 (C 프로그램에서 가능한 한) 확실하게 하기 위해 다음을 제안합니다.
- 에 의해 반환된 오류를 적절히 처리합니다.
fwrite(). - 불러
fflush()개천을 닫기 전에다음에 의해 반환된 오류를 확인하는 것을(를)fflush().
응용 프로그램의 맥락에서 fclose()가 실패할 경우 유용한 작업을 생각할 수 있다면 반환 값을 테스트합니다.안되면 그러지 마.
언급URL : https://stackoverflow.com/questions/1954273/fclose-return-value-check
'programing' 카테고리의 다른 글
| Github 개인 저장소에 대한 Jenkins CI 인증 (0) | 2023.10.14 |
|---|---|
| 모델을 사용하지 않고 엔티티 프레임워크를 사용하여 원시 SQL 쿼리를 실행하는 방법은 무엇입니까? (0) | 2023.10.14 |
| CUDA의 __공유_메모리는 언제 유용합니까? (0) | 2023.10.14 |
| vue.js에서 상위 메서드에 액세스하는 방법 (0) | 2023.10.14 |
| scikit 카운트 벡터라이저에서 min_df 및 max_df 이해 (0) | 2023.10.09 |