Почему strdup считается злом

Я видел несколько плакатов о том, что strdup это зло Есть ли консенсус по этому вопросу? Я использовал его без каких-либо чувства вины и не вижу причин, почему это хуже, чем использовать malloc/memcpy,

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


Спасибо за ответы и извинения тем, кто считает вопрос бесполезным (голосует за закрытие). Подводя итоги ответов, кажется, что нет общего ощущения, что strdup это само по себе зло, но общее мнение, что оно, как и многие другие части C, может использоваться ненадлежащим образом или небезопасно.

На самом деле не существует "правильного" ответа, но ради его принятия я принял ответ @nneoneo - в равной степени это мог быть ответ @R...

7 ответов

Решение

Я могу придумать две причины:

  1. Это не строго ANSI C, а скорее POSIX. Следовательно, некоторые компиляторы (например, MSVC) не рекомендуют использовать (MSVC предпочитает _strdup), и технически стандарт C мог бы определить свой собственный strdup с другой семантикой, так как str является зарезервированным префиксом Таким образом, существуют некоторые потенциальные проблемы с переносимостью при его использовании.
  2. Это скрывает распределение памяти. Большинство других str функции не выделяют память, поэтому пользователи могут быть введены в заблуждение (как вы говорите), полагая, что возвращаемую строку не нужно освобождать.

Но, помимо этих моментов, я думаю, что осторожное использование strdup оправдано, так как это может уменьшить дублирование кода и обеспечивает хорошую реализацию для распространенных идиом (таких как strdup("constant string") чтобы получить изменяемую, возвращаемую копию литеральной строки).

Мой ответ скорее поддерживающий strdup и это не хуже, чем любая другая функция в C.

  1. POSIX является стандартом и strdup не слишком сложно реализовать, если переносимость становится проблемой.

  2. Освободить ли память, выделенную strdup не должно быть проблемой, если кто-то потратил немного времени, чтобы прочитать страницу руководства и понять, как strdup работает. Если человек не понимает, как работает функция, очень вероятно, что человек что-то испортит, это применимо к любой функции, а не только strdup,

  3. В C память и большинство других вещей управляются программистом, поэтому strdup ничуть не хуже, чем забыть освободить malloc 'память, не может завершить строку нулем, используя неверную строку формата в scanf (и вызывает неопределенное поведение), доступ к висячему указателю и т. д.

(Я действительно хотел опубликовать это как комментарий, но не мог добавить ни одного комментария. Следовательно, разместил это как ответ).

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

  1. Это не стандартный C (но в POSIX). Однако я нахожу эту причину глупой, потому что это почти однострочная функция для добавления в системы, в которых ее нет.
  2. Слепое дублирование строк повсеместно, а не использование их на месте, когда это возможно, тратит время и память и вводит случаи сбоев в код, которые в противном случае могли бы быть безотказными.
  3. Когда вам нужна копия строки, скорее всего, вам действительно нужно больше места для ее модификации или сборки, и strdup не дает вам этого.

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

Многие люди, очевидно, нет, но я лично нахожу strdup зло по нескольким причинам,

  • главное, что скрывает распределение. Другой str* функции и большинство других стандартных функций не требуют free потом так strdup выглядит достаточно безобидным, и вы можете забыть убрать после него. dmckee предложил просто добавить его в свой список функций, которые необходимо очистить после, но почему? Я не вижу большого преимущества в сокращении двух линий средней длины до одной короткой.

  • Он всегда выделяет память в куче, и с V99 C (это 99?) У вас есть еще одна причина, чтобы просто использовать strcpy (тебе даже не нужно malloc). Вы не можете всегда делать это, но когда вы можете, вы должны.

  • Это не является частью стандарта ISO (но это часть стандарта POSIX, спасибо Wiz), но это действительно небольшой вопрос, поскольку R... упомянул, что его можно легко добавить. Если вы пишете переносимые программы, я не уверен, как вы скажете, было ли оно уже определено или нет...

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

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

Почему strdup считается злом

  1. Конфликты с будущими языковыми направлениями .

  2. Опора на государство.

  3. Легче сделать свой, не совсем похожий на POISX или будущий C2x.


С C2x на подходе с определенным включением БП, до этого пользовался этими проблемами.

  • C2x не упоминает, тогда как POSIX делает. Код, который зависит от установкиENOMEMилиEINVALмогут возникнуть проблемы в будущем.

  • C2x Предлагаемыйпредложил char *strdup(const char *s1)использует в качестве параметра. Пользовательские версии слишком часто используютchar *s1, вызывая разницу, которая может сломать код выбора, учитывающийchar *подпись. Указатели функций IE.

  • Пользовательский код, который сделал свой собственный, не следовал указаниям языка CFuture с его «Имена функций, которые начинаются с str, mem или wcs, и строчная буква может быть добавлена ​​к объявлениям в заголовке <string.h>» и поэтому может вызвать конфликты библиотек с новыми и пользовательскими .

Если код пользователя хочетstrdup()код перед C2x, подумайте о том, чтобы назвать его по-другому, например, и использоватьconst char *параметр. Минимизируйте или избегайте любой зависимости от состоянияerrnoпосле возврата вызоваNULL.

Мойmy_strdup() усилия - бородавки и все.

Моя причина неприязни к strdup, о которой не упоминалось, заключается в том, что это распределение ресурсов без естественной пары. Давайте попробуем глупую игру: я говорю malloc, ты говоришь free, Я говорю open ты говоришь close, Я говорю create ты говоришь destroy, Я говорю strdup ты говоришь....?

Собственно, ответ на strdup является free конечно, и функция была бы лучше названа malloc_and_strcpy чтобы прояснить это. Но многие программисты на Си так не думают об этом и забывают, что strdup требует его противоположности или "окончания" free освободить.

По моему опыту, очень часто можно найти утечки памяти в коде, который вызывает strdup, Это странная функция, которая объединяет strlen, malloc а также strcpy,

Другие вопросы по тегам