Kiedy ludzie mówią „ strcpy()
jest niebezpieczny, użyj strncpy()
zamiast tego” (lub podobne stwierdzenia dotyczące strcat()
itp., Ale zamierzam się strcpy()
tutaj skupić), mają na myśli, że nie ma żadnych ograniczeń strcpy()
. Dlatego zbyt długi ciąg spowoduje przepełnienie bufora. Mają rację. Użycie strncpy()
w tym przypadku zapobiegnie przepełnieniu bufora.
Wydaje mi się, że to strncpy()
naprawdę nie naprawia błędów: rozwiązuje problem, którego dobry programista może łatwo uniknąć.
Jako programista C musisz znać rozmiar docelowy, zanim zaczniesz kopiować łańcuchy. Takie jest założenie strncpy()
i strlcpy()
ostatnie parametry: dostarczasz im ten rozmiar. Możesz również poznać rozmiar źródła przed skopiowaniem ciągów. Następnie, jeśli miejsce docelowe nie jest wystarczająco duże, nie dzwoństrcpy()
. Albo zmień przydział bufora, albo zrób coś innego.
Dlaczego mi się nie podoba strncpy()
?
strncpy()
w większości przypadków jest złym rozwiązaniem: Twój ciąg zostanie obcięty bez powiadomienia - wolałbym napisać dodatkowy kod, aby rozwiązać ten problem samodzielnie, a następnie podjąć działania, które chcę wykonać, zamiast pozwolić, aby jakaś funkcja zdecydowała o tym ja o tym, co robić.
strncpy()
jest bardzo nieefektywny. Zapisuje do każdego bajtu w buforze docelowym. Nie potrzebujesz tych tysięcy '\0'
na końcu celu.
- Nie zapisuje zakończenia,
'\0'
jeśli miejsce docelowe nie jest wystarczająco duże. Więc i tak musisz to zrobić sam. Złożoność tego nie jest warta zachodu.
Teraz dochodzimy do strlcpy()
. Zmiany w stosunku strncpy()
do tego poprawiają, ale nie jestem pewien, czy specyficzne zachowanie strl*
uzasadnia ich istnienie: są one zbyt szczegółowe. Nadal musisz znać rozmiar docelowy. Jest bardziej wydajna niż strncpy()
dlatego, że niekoniecznie zapisuje do każdego bajtu w miejscu docelowym. Ale to rozwiązuje problem, który można rozwiązać wykonując: *((char *)mempcpy(dst, src, n)) = 0;
.
Nie sądzę, żeby ktokolwiek to powiedział strlcpy()
lub strlcat()
mógł prowadzić do problemów z bezpieczeństwem, co oni (i ja) mówią, że mogą powodować błędy, na przykład, gdy spodziewasz się, że zamiast jego części zostanie napisany pełny ciąg.
Głównym problemem jest tutaj: ile bajtów skopiować? Programista musi o tym wiedzieć, a jeśli tego nie zrobi, strncpy()
albo strlcpy()
nie będzie go uratować.
strlcpy()
i strlcat()
nie są standardowe, ani ISO C, ani POSIX. Dlatego ich użycie w programach przenośnych jest niemożliwe. W rzeczywistości strlcat()
ma dwa różne warianty: implementacja Solaris różni się od innych dla przypadków skrajnych o długości 0. To sprawia, że jest jeszcze mniej użyteczna niż w innym przypadku.
strlcpy
istrlcat
zgłosił jakiś rodzaj błędu, gdyby zderzył się z limitem rozmiaru bufora docelowego. Chociaż możesz sprawdzić zwracaną długość, aby to sprawdzić, nie jest to oczywiste. Ale myślę, że to drobna krytyka. Argument „zachęcają do używania ciągów C, więc są źli” jest głupi.