strlcpy: источник и назначение указывают на один и тот же объект
Я только начинаю понимать strlcpy.
size_t strlcpy(char *destination, const char *source, size_t size);
Мой гипотетический вопрос: что, если пункт назначения и источник указывают на один и тот же объект?
Пример:
char destination[100];
const char*source = "text";
destination = source;
strlcpy(destination, source, sizeof(destination))
Что происходит в бэкэнде?
Является strlcpy
знаете, что источник и место назначения используют один и тот же указатель?
Или
Копирует ли он вслепую и тратит циклы процессора - копируя одинаковые байты?
3 ответа
Что, если пункт назначения и источник указывают на один и тот же объект?
strlcpy()
не является частью стандартной библиотеки C. Его точная функциональность может варьироваться от компилятора к компилятору. Просмотрите документацию к конкретному компилятору / библиотеке, чтобы получить лучший ответ.
Как часть систем BSD, strlcpy(3) - справочная страница Linux, я не нашел ничего, препятствующего перекрытию.
Начиная с C99, ключевое слово restrict
помогает ответить на вопрос "Что, если место назначения и источник указывают на один и тот же объект?" часть.
Если подпись была такой, как показано ниже, чем использовать destination, source
эта ссылка на перекрывающиеся данные является неопределенным поведением. Все может случиться.
size_t strlcpy(char * restrict destination, const char * restrict source, size_t size);
Если подпись была такой, как показано ниже, а компилятор соответствует C99 или более поздней версии, чем использовать destination, source
это может перекрываться определенным поведением.
Если подпись была такой, как показано ниже, и компилятор не жалуется на C99 или более позднюю версию, чем использовать destination, source
это может перекрываться, вероятно, неопределенное поведение, если в документации не рассматривается этот случай.
size_t strlcpy(char * destination, const char *source, size_t size);
Поскольку strlcpy
не определен ни стандартом ISO C, ни каким-либо другим "официальным" стандартом, о котором я знаю, на этот вопрос не обязательно есть канонический ответ.
Наиболее близким к официальной спецификации этой функции, вероятно, является справочная страница OpenBSD, поскольку функция была представлена в статье, написанной в соавторстве с Тео де Раадтом, создателем OpenBSD. (Первый автор статьи - Тодд С. Миллер.) На этой странице руководства говорится:
Если строки src и dst перекрываются, поведение не определено.
В частности, вы можете увидеть в источнике, что с этой конкретной реализацией, если вы должны были сделать
char buf[20] = "hello world";
char *dest = buf+2;
strlcpy(dest, buf, 18);
тогда dest
в конечном итоге укажет на строку "heheheheheheheheh"
вместо того "hello world"
как вы, наверное, хотели.
Так как это относится по крайней мере к одной известной реализации, вам следует никогда не вызывать функцию для потенциально перекрывающихся строк, поскольку ваш код будет, по крайней мере, менее переносимым.
strlcpy скопирует длину буфера и обеспечит завершение строки 0. Он не будет проверять, совпадают ли ваши dest и src, вам нужно убедиться, что указатели нацелены на один и тот же адрес. Если нет, он просто перезапишет данные и обеспечит, чтобы последний байт dest был равен 0.