Предоставляет ли MinGW-w64 g ++ реализацию в Microsoft C11 функции getenv_s? Если да, какой заголовок будет включен?

Согласно cppreference.com, getenv_s поддерживается с C11

errno_t getenv_s( size_t *restrict len, char *restrict value,
rsize_t valuesz, const char *restrict name );

С MinGW-w64 8.1, g ++ сообщает об ошибке с обоими #include с cstdlib а также stdlib.h

use of undeclared identifier 'getenv_s'; did you mean '_wgetenv_s'?
errcode = getenv_s(&envsize, NULL, 0, name);
^~~~~~~~
_wgetenv_s

Интересно, почему MinGW-w64 g ++, по-видимому, не представляет C11 от Microsoft ucrt? getenv_s?

В С ++ у нас уже есть портативный способ получения переменных среды безопасно?

0

Решение

Редактировать:

Первоначально исправленный ответ ниже не совсем корректен. В настоящее время нет декларации для getenv_s в <sec_api/stdlib_s.h> на реализациях MinGW-w64, но вы можете объявить это самостоятельно:

#ifdef __cplusplus
extern "C" {
#endif

#include <sec_api/stdlib_s.h> /* errno_t, size_t */
errno_t getenv_s(
size_t     *ret_required_buf_size,
char       *buf,
size_t      buf_size_in_bytes,
const char *name
);

/*
* You can omit this section if you don't want to use the safer
* C++ template function in your C++ code.
*/
#ifdef __cplusplus
extern "C++" {
template <size_t size>
getenv_s(
size_t *ret_required_buf_size,
char (&buf)[size],
const char *name
) { return getenv_s(ret_required_buf_size, buf, size, name); }
}
#endif

#ifdef __cplusplus
}
#endif

На MSVC вы все равно просто используете #include <stdlib.h> как getenv_s там объявлено

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

Стоит отметить, что есть только для Windows функция называется _dupenv_s это гораздо проще использовать вместо getenv_sи вы просто освободите память, используя стандартную free функция. Объявлено в <sec_api/stdlib_s.h>, так что вы можете использовать его без проблем.


Измененный оригинальный ответ:

Во время этого ответа MinGW-w64, созданный из исходного кода, позволяет вам включать или отключать доступ к защищенным функциям CRT по умолчанию, но даже если он включен, он не помечает большинство стандартных функций C с безопасными заменами как «устаревшие» «То, как это делают заголовки CRT в Visual C ++ (на самом деле, кажется, что некоторые из них помечаются как устаревшие, но макросы расширяются до нуля в сборке, которую я использую).

Чтобы более прямо ответить на этот вопрос, реализация MinGW-w64 в настоящее время хранит прототипы для функций безопасной CRT в отдельном заголовочном файле в sec_api каталог, и этот файл заголовка не включен из стандартного заголовка C, что означает соответствующий заголовок C ++ <cstdlib> также не будет объявлять функции, поскольку включает только стандартный заголовок.

Вместо этого вам нужно явно включить нужные вам заголовки C, такие как <sec_api/stdlib_s.h>, <sec_api/stdio_s.h>и т. д., которые будут объявлять функции только в том случае, если включен безопасный API (т.е. MINGW_HAS_SECURE_API определяется до 1 в _mingw.h). Поскольку функции, вероятно, доступны для связывания, вы можете просто использовать #define MINGW_HAS_SECURE_API 1 перед включением, чтобы разрешить использование объявленных безопасных функций или объявить функции самостоятельно в случае, если они не объявлены.

Я чувствую, что стоит упомянуть, что многие, хотя и не все, C ++ — только шаблонные функции, такие как

// #include <sec_api/string_s.h> in MinGW-w64.
// #include <string.h> (C) or <cstring> (C++) in MSVC.
template <size_t size>
errno_t strcpy_s(
char      (&dest)[size],
const char *src
);

объявлены и реализованы.

На основе примеры в документации Microsoft и вывод препроцессора в случае MinGW-w64, обе реализации помещают защищенные функции в глобальное пространство имен C ++, а не в std пространство имен (например, strcpy_s в его полностью квалифицированной форме ::strcpy_s) поскольку они не являются стандартными функциями C ++.

1

Другие решения

В c ++, у нас уже есть переносимый способ безопасного извлечения переменных среды?

Ты можешь использовать getenv, Если вы не хотите иметь необработанный указатель на строку C, принадлежащую кому-то другому, просочившуюся в ваш код, вы можете использовать std::optional:

#include <cstdlib>
#include <optional>
std::optional<std::string> get_env(const char* env) {
auto t = std::getenv(env);
if (t) return t;
return {};
}

Полный пример.

PS: даже если бы он был доступен в C ++, я не уверен, что буду использовать getenv_s, resitrct не является стандартным C ++, и передача массивов и их размер отдельно не очень идиоматический C ++. Насколько я понимаю getenv_s это улучшение getenv в C, где вам нужно как-то иметь дело с нулевыми указателями и длинами строк, в то время как в C ++ у нас есть различные доступные решения (std::string для строк переменной длины и std::optional для необязательных значений).

3

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector