Коли люди кажуть: " 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, і тому вони погані" - дурний.