Когда люди говорят: « 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. Это делает ее даже менее полезной, чем в противном случае.
strlcpyиstrlcatхотел сообщить какие - то условие ошибки , если они торкались ограничением размера буфера назначения. Хотя вы можете проверить возвращенную длину, чтобы проверить это, это не очевидно. Но я думаю, что это незначительная критика. Аргумент «они поощряют использование строк C, поэтому они плохие» - глупый.