2012-10-15 12 views
20

Z cplusplus.comCo to jest gets() w C11?

Ostatnie zmiany wzorca C (2011) definitywnie usunięto funkcji od specyfikacją

funkcja zostanie wycofany, C++ (zgodnie z normą 2011, który następuje C99 + TC3).

Chciałem tylko wiedzieć, co jest alternatywą dla gets() w standardzie C11?

+2

fgets (..., ..., stdin) –

Odpowiedz

15

W C11 gets została zastąpiona przez gets_s który ma następującą deklarację:

char *gets_s(char *str, rsize_t n); 

Funkcja ta przeczytać co najwyżej n-1 znaki z stdin w *str. Ma to na celu uniknięcie luki w zabezpieczeniach polegającej na przepełnieniu bufora, która jest nieodłączna od gets. Funkcja fgets jest również opcją. Od http://en.cppreference.com/w/c/io/gets:

gets() funkcja nie wykonuje sprawdzanie granic, dlatego ta funkcja jest niezwykle podatny na przepełnienie bufora ataków. Nie można go bezpiecznie używać (chyba że program działa w środowisku, które ogranicza to, co może pojawić się na stdin). Z tego powodu funkcja została wycofana w trzecim sprostowaniu do standardu C99 i usunięta całkowicie w standardzie C11. fgets() i gets_s() są zalecanymi zamiennikami.

Nigdy nie używaj pobiera().

Zważywszy, że gets_s jest zdefiniowane w rozszerzenie standardu, tylko ewentualnie wdrożony, należy prawdopodobnie pisać swoje programy za pomocą fgets zamiast. Jeśli użyjesz fgets na stdin Twój program będzie również kompilował we wcześniejszych wersjach C. Pamiętaj jednak o różnicy w zachowaniu: gdy gets_s odczytał n-1 znaków , kontynuuje czytanie aż do momentu, gdy nowa linia lub koniec pliku zostanie osiągnięty , odrzucając dane wejściowe. Tak więc z gets_s zawsze czytasz całą linię, nawet jeśli tylko jej część może zostać zwrócona w buforze wejściowym.

+6

Należy zauważyć, że 'gets_s' jest opcjonalne, nie musi być obecne, jeśli implementacja nie definiuje' __STDC_LIB_EXT1__', a jeśli tak, potrzebuję '__STDC_WANT_LIB_EXT1__' zdefiniowanego jako 1 (jeśli to w ogóle nie jest zdefiniowane, to implementacja określić, czy funkcje w załączniku K są zawarte w odpowiednich nagłówkach). –

+6

Należy użyć 'fgets'. 'gets_s' to opcjonalny interfejs, który istnieje tylko w systemie Windows i został wymieniony w standardzie tylko z powodów politycznych.Prawie każdy poza SM stwierdzi, że interfejsy są błędne i szkodliwe. Podobno zestandaryzowane zachowanie niektórych lub wszystkich interfejsów różni się nawet od istniejących tylko implementacji (MS), czyniąc ich użycie jeszcze bardziej szkodliwym. –

+0

Podejrzewam, że źle zrozumiałeś zachowanie gets_s. Podobnie jak fgets, odczytuje co najwyżej n-1 znaków. Różnica polega na tym, że gets_s zatrzymuje się, jeśli napotka nowy znak linii. Nic w standardzie nie oznacza, że ​​czyta po n-1. Nie należy mylić standardowej wersji z różnymi niestandardowymi implementacjami, które istniały przed C11. – Lundin

4

Zgodnie z man 3 gets, fgets.

+0

dostaje równowartość w standardzie C11 jest gets_s, chociaż powinno być technicznie samo jak fgets (..., stdin); – Lundin

+1

"W opcjonalnym załączniku dodanym z powodów politycznych" prawie nie ma "w standardzie C11". Nie znajdziesz nigdzie wersji funkcji _s zgodnej z C11, ponieważ nikt nie planuje ich implementacji. –

+2

@R .. Załącznik K C11 jest normatywny, nawet jeśli nie jest obowiązkowy. W praktyce oznacza to, że implementacje C nie mogą już zawierać dziwnych, niestandardowych funkcji get_s, które mają działanie kolidujące ze standardem. Założę się również, że GCC wdroży te funkcje: ten kompilator po prostu kocha opcjonalne, zbędne, bezsensowne funkcje. Chciałbym jednak polecić fgets(), ze względu na kompatybilność. – Lundin

8

Inni już odpowiedzieli na pytanie. W celu uzupełnienia, jest to zalecenie standardu C:

ISO9899: 2011 K.3.5.4.1/6

Zalecana praktyka

Funkcja fgets pozwala poprawnie napisane programy bezpiecznie przetwarzać linie wejściowe zbyt długie przechowywanie w wyniku tablicy. Zasadniczo wymaga to, aby wywoływacze fgetów zwracały uwagę na obecność lub brak znaku nowej linii w tablicy wyników. Rozważ użycie fgets (wraz z potrzebnym przetwarzaniem opartym na znakach nowej linii) zamiast gets_s.

Więc należy użyć fgets w miarę możliwości.

EDIT

gets_s zachowanie jest określony jako:

ISO9899: 2011 K.3.5.4.1/4

Opis

Funkcja gets_s czyta co najwyżej jeden mniej niż liczba znaków określonych przez n ze strumienia wskazywanego przez stdin, do tablicy wskazywanej przez s. Żadne dodatkowe znaki nie są czytane po znaku nowej linii (który jest odrzucany) lub po końcu pliku. Odrzucony znak nowej linii nie jest wliczany do liczby odczytanych znaków. Znak zerowy jest zapisywany bezpośrednio po wczytaniu ostatniego znaku do tablicy.

Jeśli EOF spotyka i nie ma żadnych znaków czytać do tablicy, lub w przypadku pojawienia się czytać błąd podczas operacji, a następnie s [0] jest ustawiony na znak null, a pozostałe elementy s przyjmują nieokreślone wartości.

+3

Zauważ, że 'gets_s()' zgłasza naruszenie ograniczenia, jeśli nie ma ani nowej linii, ani EOF w obrębie znaków 'n-1'; błędem jest uzyskanie zbyt długiej linii. –