2008-11-13 20 views
5

Wygląda na to, że następujące połączenia wykonują to, czego oczekujesz (zamknij strumień i nie zezwalaj na żadne dodatkowe dane wejściowe - wszystko, co czeka na dane wejściowe na temat błędu zwracania strumienia), ale czy jest ono gwarantowane we wszystkich kompilatorach/platformach?Czy close/fclose na stdin jest poprawne?

close(fileno(stdin)); 
fclose(stdin); 
+1

możesz po prostu fclose (stdin), to wywoła metodę close() na uchwycie pliku. –

Odpowiedz

3

Nie ma gwarancji poprawności we wszystkich możliwych systemach operacyjnych. Jednak wywołanie fclose (stdin) będzie działało na dowolnym systemie operacyjnym zgodnym z POSIX, jak również na systemach operacyjnych Windows, więc powinieneś trafić praktycznie wszystko, co aktualnie używasz.

Jak stwierdzono w poprzedniej odpowiedzi, a także w moim komentarzu, nie trzeba wywoływać zamknięcia w uchwycie pliku. fclose() właściwie zamknie wszystko dla ciebie.

14

NIE ZACZYNAJ zamknąć pliku (FILE *). FILE jest obiektem buforującym. Zaglądanie w jego implementację i wtrącanie się w jej stan niesie ze sobą wszystkie zastrzeżenia i niebezpieczeństwa, które miałyby podobne niedociągnięcia w jakimkolwiek innym module oprogramowania.

Nie rób tego.

AGH. Poważnie. Paskudny.

+5

W rzeczywistości wykonanie close() przed fclose() gwarantuje, że fclose() zakończy się niepowodzeniem, jeśli do wypłukania zostaną zaległe dane. (W bardziej ogólnym przypadku, gdzie może być inny kod między close() i fclose(), fclose() może po prostu napisać do niewłaściwego pliku!) –

+0

To ... nie ... technicznie odpowiedzieć na pytanie . –

+0

To robi: Zachowanie kodu OP byłoby niezdefiniowane. Jest mało prawdopodobne, aby jego implementacja fclose wykryła, że ​​fd zostało zamknięte. Jeśli między wywołaniami zamknięcia i fclose nastąpiły inne rzeczy, jest jeszcze jedna nieprzyjemna możliwość: po zamknięciu deskryptora pliku, następne wywołanie funkcji open() jest w praktyce - w praktyce - ponownym użyciem deskryptora pliku. Co by się stało, gdybyś zadzwonił blisko bazowego deskryptora, otworzył inny deskryptor z tym samym indeksem, a następnie wywołał fclose? Ta ostatnia faza open() z pewnością byłaby zła. – Sniggerfardimungus

17

fclose(stdin) powoduje dalszego korzystania z stdin (bezpośrednia lub pośrednia) do wywołania niezdefiniowanej zachowanie, które jest bardzo złe. Nie "hamuje wejścia".

close(fileno(stdin)) powoduje żadnych dalszych prób wejścia z stdin po bieżący bufor został wyczerpany, by upaść z EBADF, ale tylko do momentu otwarcia innego pliku, w tym przypadku, że plik będzie stać fd # 0 i złe rzeczy zdarzyć się.

Bardziej zdecydowane podejście może być:

int fd = open("/dev/null", O_WRONLY); 
dup2(fd, 0); 
close(fd); 

z kilkoma dodanymi kontroli błędów. Zapewni to, że wszystkie odczyty (po wyczerpaniu bieżącego bufora) spowodują błędy. Jeśli chcesz tylko, aby skutkowały EOF, a nie błędem, użyj O_RDONLY zamiast O_WRONLY.

Powiązane problemy