Если я использую защищенные версии функций POSIX на MSVC - C

Я пишу некоторый код 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    
}

Какие-либо мысли?

6
задан Navaneeth K N 8 July 2010 в 11:46
поделиться

3 ответа

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

Мой совет таков: Каким бы ни был ваш окончательный выбор, хорошей идеей будет следовать принципу DRY и продолжать делать все так, как в вашем примере my_strcpy(). Не разбрасывайте необработанные вызовы по всему коду, используйте обертки и централизуйте их в вашей собственной библиотеке обработки строк. Это сократит общий объем кода (boilerplate), и у вас будет одно центральное место для внесения изменений, если вы передумаете позже.

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

4
ответ дан 10 December 2019 в 02:42
поделиться

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

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

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

4
ответ дан 10 December 2019 в 02:42
поделиться

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

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

1
ответ дан 10 December 2019 в 02:42
поделиться
Другие вопросы по тегам:

Похожие вопросы: