Почему нет проверки работоспособности в устаревшем strcpy () - PullRequest
10 голосов
/ 01 сентября 2010

Ниже приведена самая популярная реализация strcpy в традиционных системах. Почему dest и src не проверяются на NULL в начале? Однажды я слышал, что в старые времена память была ограничена, поэтому короткий код всегда предпочитался. Будете ли вы реализовывать strcpy и другие подобные функции с проверками NULL-указателей в первые дни? Почему нет?

char *strcpy(char *dest, const char *src)
{
   char *save = dest;
   while(*dest++ = *src++);
   return save;
}

Ответы [ 9 ]

20 голосов
/ 01 сентября 2010

NULL - плохой указатель, но (char*)0x1 тоже.Это должно также проверить это?По моему мнению (я не знаю окончательной причины, почему), проверки работоспособности в такой операции низкого уровня не нужны.strcpy() настолько фундаментально, что к нему следует относиться как к инструкции asm, и вы должны делать свои собственные проверки работоспособности в вызывающей стороне, если это необходимо.Просто мои 2 цента:)

15 голосов
/ 01 сентября 2010

Нет проверок работоспособности, потому что одна из наиболее важных базовых идеологий C состоит в том, что разработчик обеспечивает разумность.Когда вы предполагаете, что разработчик в здравом уме, вы в конечном итоге получаете язык, на котором можно делать практически все, где угодно.

Это явно не заявленная цель - для кого-то вполне возможно придуматьреализация, которая проверяет и многое другое.Может быть, они имеют.Но я сомневаюсь, что многие люди, привыкшие к C, будут требовать его использования, так как в любом случае им нужно будет поставить проверки, если есть вероятность, что их код будет перенесен в более обычную реализацию.

11 голосов
/ 01 сентября 2010

Весь язык Си написан под девизом: «Мы будем вести себя правильно, если программист знает, что он делает». Предполагается, что программист знает, как выполнить все необходимые ему проверки. Это не просто проверка на NULL, это гарантия того, что dest указывает на достаточное количество выделенной памяти для хранения src, это проверка возвращаемого значения fopen, чтобы убедиться, что файл действительно действительно открылся успешно, зная когда memcpy безопасно и когда требуется memmove и т. д.

Получение strcpy для проверки на NULL не изменит языковой парадигмы. Вам все равно нужно будет убедиться, что dest указывает на достаточно места - и это то, что strcpy не может проверить без изменения интерфейса. Вам также необходимо убедиться, что src определен '\0', что опять-таки strcpy не может проверить.

Существуют некоторые стандартные библиотечные функции C, которые do проверяют на NULL: например, free(NULL) всегда безопасен. Но в целом С ожидает, что вы будете знать, что делаете.

[C ++ обычно отказывается от библиотеки <cstring> в пользу std::string и друзей.]

6 голосов
/ 01 сентября 2010
  1. Обычно для библиотеки лучше позволить вызывающей стороне решить, какой она должна быть семантикой сбоя. Что бы вы сделали strcpy, если бы любой из аргументов был NULL?Молча ничего не делать?Сбой assert (что не доступно в сборках без отладки)?

  2. Проще подписаться, чем отказаться. Тривиально написать свою собственную обертку вокруг strcpy, которая проверяет входные данные и использовать ее вместо этого.Однако если бы библиотека делала это сама, у вас не было бы способа не выполнять эти проверки, за исключением повторной реализации strcpy.(Например, вы, возможно, уже знаете, что аргументы, которые вы передаете strcpy, не являются NULL, и это может быть чем-то, что вас волнует, если вы вызываете его в узком цикле или хотите минимизировать потребление энергии.) В целом, лучше ошибиться в сторону предоставления большей свободы (даже если эта свобода сопряжена с дополнительной ответственностью).

3 голосов
/ 01 сентября 2010

Наиболее вероятная причина: потому что strcpy не указан для работы с NULL входами (т. Е. Его поведение в этом случае не определено).

Итак, что должен выбрать исполнитель библиотеки?если NULL передается?Я бы сказал, что лучшее, что нужно сделать, - это дать приложению аварийно завершить работу.Подумайте об этом так: сбой является довольно очевидным признаком того, что что-то пошло не так ... тихое игнорирование ввода NULL, с другой стороны, может маскировать ошибку, которую будет гораздо сложнее обнаружить.

2 голосов
/ 01 сентября 2010

Проверки NULL не были реализованы, поскольку самые ранние цели C поддерживали надежную защиту памяти. Когда процесс пытался выполнить чтение или запись в NULL, контроллер памяти сообщит ЦПУ о попытке доступа к памяти вне допустимого диапазона (нарушение сегментации), и ядро ​​завершит работу нарушающего процесса.

Это был правильный ответ, потому что код, пытающийся читать или писать в нулевой указатель, не работает; Единственный ответ - переписать код, чтобы проверить возвращаемые значения от malloc(3) и друзей и предпринять корректирующие действия. К тому времени, когда вы пытаетесь использовать указатели для нераспределенной памяти, уже слишком поздно принимать правильное решение о том, как исправить ситуацию.

0 голосов
/ 01 сентября 2010

Для него просто не определена семантика ошибки. В частности, strcpy не может вернуть значение ошибки. C99 просто заявляет:

Функция strcpy возвращает значение s1.

Так что для соответствующей реализации не было бы даже возможности вернуть информацию о том, что что-то пошло не так. Так зачем с этим связываться.

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

0 голосов
/ 01 сентября 2010

По моему мнению, любая функция, которую вы хотели бы определить, имела бы предварительное условие и постусловие.Забота о предварительных условиях никогда не должна быть частью функции.Ниже приведено предварительное условие для использования strcpy, взятого со страницы руководства.

Функция strcpy () копирует строку, на которую указывает src (включая завершающий символ '\ 0'), в массив, на который указываетDest.Строки могут не перекрываться, и строка назначения dest должна быть достаточно большой, чтобы получить копию.

Теперь, если предварительное условие не выполнено, все может быть неопределенным.

Будь ябудет включать проверку NULL в моем strcpy сейчас.Я предпочел бы иметь другой safe_strcpy, давая безопасности приоритет, я определенно включил бы проверки NULL и обработал бы условия переполнения.И, соответственно, моё предварительное условие изменяется.

0 голосов
/ 01 сентября 2010

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

...