Коли люди кажуть: " strcpy()
небезпечно, використовуй strncpy()
замість цього" (або подібні твердження щодо strcat()
тощо, але я буду використовувати strcpy()
тут свою увагу), вони означають, що немає меж для реєстрації strcpy()
. Таким чином, занадто довгий рядок призведе до перевитрати буфера. Вони правильні. Використання strncpy()
в цьому випадку запобіжить перевищення буфера.
Я відчуваю, що strncpy()
насправді не виправляє помилки: це вирішує проблему, якої може легко уникнути хороший програміст.
Як програміст на С, ви повинні знати розмір призначення, перш ніж намагатись копіювати рядки. Це припущення 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, і тому вони погані" - дурний.