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

Предупреждение C4996: эта функция или переменная может быть небезопасной - по сравнению с GCC на POSIX

Я замечаю, что компиляторы MS дают "устаревшие" предупреждения для cstdlib функций типа getenv. MS изобрела свой собственный стандарт, такой как _dupenv_s.

Вопрос 1

AFAIK главная "небезопасная" вещь - это повторное участие *. Поскольку MS CRT помечен как "многопоточное" (/MT), почему бы просто не заменить getenv на реентерабельную, потокобезопасную версию? Похоже, что кто-то будет зависеть от небезопасного поведения?

Вопрос 2

Я скомпилировал тот же код с GCC g++ -Wall -Wextra -Weff++ -pedantic foo.cpp, и он не дает никаких предупреждений. Итак, я думаю, это не проблема на POSIX? Как это решить? (ОК, возможно, они просто изменили поведение getenv, было бы хорошо, если бы это подтвердилось).

* Это чрезмерное обобщение, чтобы сказать, что его "только о возврате". Конечно, у нас есть такие вещи, как strncpy_s, который полностью меняет подпись и имеет дело с размером буфера. Но не меняет суть этого вопроса.

4b9b3361

Ответ 1

  • В здравом мире ответ будет "конечно, нет, это было бы глупо!" В этом мире, однако, кажется, что нет конца ужасно плохо продуманного недокументированного поведения, от которого люди будут опускаться в зависимости от. Раймонд Чен имеет большую коллекцию таких анекдотов (anecdon'ts?) в своем блоге. Например, отвратительная практика использования ошибки в загрузчике для обмена потоковыми локальными переменными между exe и DLL. Когда у вас так много клиентов, как Microsoft, единственный безопасный выбор - никогда не рискуйте нарушить совместимость.

  • Разница в предупреждениях заключается в том, что cl.exe делает все возможное, чтобы выделить потенциальную проблему безопасности, а g++ - нет. getenv и puts, а друзья все еще разбиты под POSIX, но (по крайней мере, для getenv) в стандартной библиотеке нет более безопасной альтернативы. И, в отличие от Microsoft, люди GNU, вероятно, видят стандартный вызов библиотеки с потенциальными проблемами безопасности как меньшее зло, чем более безопасный, но специфичный для платформы вызов библиотеки.

Ответ 2

Это раздражает то, что Microsoft решила сделать это. Я знаю, как безопасно вызывать все функции, я не хочу или не нуждаюсь в этих дополнительных предупреждениях.

Просто установите _CRT_SECURE_NO_WARNINGS и сделайте с ним. Это действительно так глупо.

Ответ 3

В конкретном случае getenv он действительно не является реентерабельным или потокобезопасным. Что касается того, почему Microsoft не просто заменяет его, вы не можете взять этот интерфейс и сделать его реентерабельным (вы можете почти сделать его "потокобезопасным" с локальным хранилищем потоков, но он все равно не будет реентерабельным).

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

Действительно, используя переменные среды для чего-либо, кроме "настройки его перед запуском процесса или при запуске процесса, и только чтение из него с этой точки", вероятно, закончится слезами, если у вас есть несколько потоков. setenv и putenv не имеют достаточно богатого интерфейса, чтобы выразить что-то вроде "установить этот набор переменных среды атомарно", а также getenv не имеет возможности выразить "читать этот набор переменных среды атомарно",

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