Когда люди говорят: «strcpy()
опасно, вместо этого используйте strncpy()
» (или аналогичные утверждения о strcat()
и т. Д., Но я собираюсь использовать здесь strcpy()
в качестве своей цели), они имеют в виду, что там нет проверки границ в strcpy()
. Таким образом, слишком длинная строка приведет к переполнению буфера. Они верны. Использование strncpy()
в этом случае предотвратит переполнение буфера.
Я чувствую, что strncpy()
действительно не исправляет ошибки: это решает проблему, которую может легко избежать хороший программист.
Как программист C, вы должны знать размер места назначения, прежде чем пытаться копировать строки. Это предположение относится и к последним параметрам strncpy()
и strlcpy()
: вы задаете им этот размер. Вы также можете узнать исходный размер, прежде чем копировать строки. Затем, если пункт назначения недостаточно велик, не звоните strcpy()
. Перераспределите буфер или сделайте что-нибудь еще.
Почему мне не нравится strncpy()
?
strncpy()
в большинстве случаев является плохим решением: ваша строка будет обрезана без какого-либо уведомления - я бы лучше написал дополнительный код, чтобы выяснить это сам, а затем предпринять действия, которые я хочу предпринять, скорее чем позволить какой-то функции решить для меня, что делать.
strncpy()
очень неэффективно. Он записывает каждый байт в буфере назначения. Вам не нужны эти тысячи '\0'
в конце пункта назначения.
- Не пишется завершающий
'\0'
, если место назначения недостаточно велико. Так что, вы все равно должны сделать это сами. Сложность этого не стоит.
Теперь мы подошли к strlcpy()
. Изменения с strncpy()
делают его лучше, но я не уверен, что конкретное поведение strl*
оправдывает их существование: они слишком специфичны. Вы все еще должны знать размер пункта назначения. Это более эффективно, чем strncpy()
, потому что оно не обязательно записывает каждый байт в месте назначения. Но это решает проблему, которую можно решить, выполнив: *((char *)mempcpy(dst, src, n)) = 0;
.
Не думаю, что кто-то говорит, что strlcpy()
или strlcat()
могут привести к проблемам с безопасностью, что они (и я) говорят, что могут привести к ошибкам, например, когда вы ожидаете, что полная строка будет написано вместо его части.
Основная проблема здесь: сколько байт нужно скопировать? Программист должен знать это, и если он этого не сделает, strncpy()
или strlcpy()
не спасут его.
strlcpy()
и strlcat()
не являются стандартными, ни ISO C, ни POSIX. Таким образом, их использование в переносимых программах невозможно. Фактически, strlcat()
имеет два различных варианта: реализация Solaris отличается от других для краевых случаев, имеющих длину 0. Это делает его даже менее полезным, чем в противном случае.