Должен ли я использовать безопасные версии функций POSIX на MSVC - C - PullRequest
6 голосов
/ 08 июля 2010

Я пишу некоторый код C, который, как ожидается, будет компилироваться на нескольких компиляторах (по крайней мере, на MSVC и GCC). Поскольку я новичок в C, у меня включены все предупреждения, и предупреждения рассматриваются как ошибки (-Werror в GCC и /WX в MSVC), чтобы я не делал глупых ошибок.

Когда я скомпилировал код, который использует strcpy в MSVC, я получаю предупреждение вроде

warning C4996: 'strcpy': This function or variable may be unsafe. Consider using strcpy_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.

Я немного растерялся. Многие общие функции устарели в MSVC. Должен ли я использовать эту защищенную версию в Windows? Если да, я должен обернуть strcpy что-то вроде,

my_strcpy()
{
#ifdef WIN32
 // use strcpy_s
#ELSE
 // use strcpy    
}

Есть мысли?

Ответы [ 3 ]

4 голосов
/ 08 июля 2010

Здесь, на SO, много и много дискуссий на эту тему.Я уверен, что обычные подозреваемые, такие как strncpy, strlcpy и все, что появится здесь снова, я уверен.Просто введите «strcpy» в поле поиска и прочитайте некоторые более длинные темы, чтобы получить обзор.

Мой совет: каким бы ни был ваш окончательный выбор, будет хорошей идеей следовать принципу СУХОЙ и продолжатьсделать это, как в вашем примере my_strcpy ().Не бросайте необработанные вызовы по всему коду, используйте обертки и централизуйте их в своей собственной библиотеке обработки строк.Это уменьшит общий код (шаблон), и у вас будет одно центральное место для внесения изменений, если вы передумаете позже.

Конечно, это открывает некоторые другие банки червей, особенно для новичка: обработка памятиответственность и дизайн интерфейса.Как отдельная тема, так и 5 человек дадут вам 10 советов, как это сделать.Центральная библиотека обычно имеет приятный эффект, заключающийся в том, что она обеспечивает выполнение решения, которому вы будете следовать на протяжении всей своей кодовой базы, вместо использования метода a в модуле A и метода b в модуле B, что вызывает проблемы при попытке соединить A с B...

4 голосов
/ 08 июля 2010

Всякий раз, когда вы перемещаете данные между буферами не постоянного размера, вы должны (задыхаться! Omg!) На самом деле подумать о том, подходит ли оно.Использование функций (например, специфичных для MS strcpy_s или BSD strlcpy), которые якобы «безопасны», защитит вас от некоторых явных условий переполнения буфера, но не защитит вас от ошибокэто результат усечения строки.Это также не защитит вас от целочисленных переполнений при вычислении буферов необходимого размера.

Если вы не разбираетесь в строках C, я бы рекомендовал забыть о специальных функциях и комментировать каждые строка вашего кода, которая будет выполнять запись переменной длины / позиции с обоснованием того, как вы знаете, в данный момент в программе, что длина / смещение, которое вы собираетесь использовать, находится в пределах размера буфера,Сделайте это для строк, где вы также выполняете арифметику для размеров / смещений - запишите, как вы знаете, что арифметика не будет переполнена, и добавьте тесты на переполнение, если вы обнаружите, что вы не знаете.оберните всю вашу обработку строк в строковый объект, который хранит длину буфера вместе со строкой и автоматически перераспределяет, когда строка должна быть увеличена, и затем используйте const char * только для чтения для доступа к строкам, когда вам нужно передатьих к системным функциям или другим библиотекам.Это принесет в жертву большую часть производительности, которую вы ожидаете от C, но поможет вам избежать ошибок.Только не доводите это до крайности.Нет необходимости дублировать такие вещи, как strchr, strstr и т. Д. В вашей обёртке строки.Просто предоставьте методы для дублирования строковых объектов, их объединения и усечения, а затем с помощью существующих библиотечных функций, работающих с const char *, вы можете делать практически все, что захотите.

1 голос
/ 08 июля 2010

Я бы предпочел использовать более безопасную функцию snprintf †, которая доступна на обеих платформах, а не иметь разные пути в зависимости от платформы.Вам нужно будет использовать определение, чтобы предотвратить появление предупреждений в MSVC.

†, хотя, возможно, немного менее безопасно - он вернет строку, которая не завершается нулем при ошибке, поэтому вы должны проверить возврат, но это не приведет к переполнению буфера.

...