Подтвердить что ты не робот

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

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

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


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

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

4b9b3361

Ответ 1

Две причины, о которых я могу думать:

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

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

Ответ 2

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

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

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

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

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

Ответ 3

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

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

Ответ 4

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

Ответ 5

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

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

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

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

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

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

Ответ 6

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

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

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