и strcpy... хотите заменить и strcpy рудник, который функції strncpy и null прекратить

ключ находится в названии, но в основном я унаследовал некоторый код, который имеет 800+ экземпляров strcpy. Я хочу написать новую функцию, а затем заменить strcpy на strcpy_mine.

поэтому я пытаюсь выяснить, какой список параметров будет иметь strcpy_mine.

пробовал:

void strcpy_mine( char* pTarget, const char* const pCopyMe )
{
  const unsigned int lenAlwaysFour = sizeof(pCopyMe ); //:(
  strncpy( pTarget, pCopyMe, lenAlwaysFour );

  //add extra terminator in case of overrun
  pTarget[lenAlwaysFour] = 0;
}

но sizeof всегда 4 pCopyMe является указателем

то, что я не хочу делать, это заменить

strcpy (buf, pCopyMe);

С

strncpy (buf, pCopyMe, sizeof(pCopyMe)); buf[sizeof(pCopyMe)] = 0;

какие идеи? (strcpy_l не доступен)

ура

7 ответов


в зависимости от того, как выглядят сайты вызовов, часто большинство случаев может быть обработано простым шаблоном:

#include <string.h>

template <int bufferSize>
void strcpy_mine( char (&pTarget)[bufferSize], const char* const pCopyMe )
{
  strncpy( pTarget, pCopyMe, bufferSize-1 );

  //add extra terminator in case of overrun
  pTarget[bufferSize-1] = 0;
}

int main()
{
  char buf[128];
  strcpy_mine(buf,"Testing");
  return 0;
}

Если вы используете Microsoft Visual Studio 2005 или новее, см. раздел Безопасные Перегрузки Шаблонов для реализации Microsoft.


оператор sizeof() возвращает размер типа в этом случае const char* const который будет 4 на 32-битных машинах.

Я думаю, вы думаете, что вы хотите strlen(). Но это не правильный способ использования функций strncpy. Вам нужен размер выход буфер для strncpy.

чтобы исправить это, вам нужно изучить код на каждом сайте вызовов и разработать размер выходного буфера и передать его в качестве аргумента strcpy_mine. Если вызов-сайт для strcpy (или strcpy_mine) не знает размер выходного буфера, вам нужно выполнить поиск назад в коде для местоположения, которое выделяет буфер, и передать размер вплоть до сайта strcpy.

В основном вы не можете написать замену strcpy, которая принимает те же аргументы и надеется избежать проблем, которые привели к strncpy в первую очередь (и лучшие замены за пределами этого). Вы можете создать функцию, которая принимает те же аргументы, что и strncpy, но гарантирует, что результат null-terminated-посмотрите на реализацию strlcpy () OpenBSD


немного периферийный, возможно, но так как никто не упоминал об этом, и он щеголяет в названии: вы не можете (юридически) написать глобальную функцию под названием strcpy_mine().

"пространство имен" функций, имена которых начинаются с str зарезервированы для стандартной библиотеки. См., например, принятый ответ на этот вопрос.


вы можете использовать тот же список параметров, что и strncpy для вашего strcpy_mine, но напишите его так, чтобы он всегда заканчивал результат null. Это будет не так уж трудно.

одна из проблем, однако, заключается в том, что некоторые из вашего существующего кода, который вызывает strcpy (), также могут не знать размер буфера.


также вы можете использовать макросы для избежания множественных правок. Или автоматизировать редактирование с помощью скрипта.


вам определенно нужно передать размер целевого буфера в качестве параметра, как говорили другие люди выше.

это своего рода не по теме, но я просто хочу отметить, что после использования strncpy(), вам нужно установить значение null последнего символа буфера, который имеет индекс 1 меньше чем длина (не длина буфера):

strncpy (buf, pCopyMe, buflen); buf[buflen - 1] = '';

или альтернативно, вы можете использовать strncat() на пустой строке, передавая ей длину, которая на 1 меньше, и это гарантирует нулевое завершение вашей строки:

buf[0] = ''; strncat (buf, pCopyMe, buflen - 1);

Leeder Дуглас это правильно. Существует предел полезности замены strcpy, если вы не хотите выполнять тяжелую работу по передаче хорошей, разумной длины буфера в каждом случае. Это большая работа!

хорошая новость в том, что это того стоит! Несколько лет назад я участвовал в нескольких проектах на C++, которые были запоздалыми, ошибочными и ненадежными. Объявив strcpy и strlen запрещенными, и взяв 2-3 дня из проекта, чтобы заменить их на пользовательские strncpy / strnlen, во всех этих проектах мы внезапно могли работать в течение нескольких дней, а не часов. Мы также видели много усеченных строк, выходящих на экранные дисплеи и файлы журналов. Это дало нам подсказки, необходимые для отслеживания проблем усечения, ранее сбоев.

Если вы не хотите этого делать, вы можете получить гораздо меньшее преимущество, просто проверив оба параметра указателя на NULL и ограничив максимальный размер копии строки и протокол о том, что граница достигнутый. не делайте strlen любого параметра, так как strlen будет счастливо сбой на вас, если строка не будет должным образом null завершена.

В настоящее время новые проекты используют хорошие строковые объекты, но есть много устаревшего кода, который этого не делает.