MinGW-w64 g++ 是否公开了微软 ucrt 对 C11 `getenv_s` 函数的实现?如果是,要包括什么header?
Does MinGW-w64 g++ expose microsoft ucrt's implementation of C11 `getenv_s` function? If yes, what header to be included?
根据 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++ 似乎没有暴露微软 ucrt 的 C11 getenv_s?
在 c++ 中,我们是否已经有了 可移植 安全检索环境变量的方法?
In c++, do we already have a portable way to retrieve environment variables safely?
您可以使用 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
是对 C 中 getenv
的改进,您需要以某种方式处理空指针和字符串长度,而在 C++ 中,我们有不同的解决方案(std::string
用于可变长度字符串和 std::optional
可选值)。
编辑:
下面最初修改的答案并不完全正确。目前在 MinGW-w64 实现上 <sec_api/stdlib_s.h>
中没有 getenv_s
的声明,但是你可以自己声明:
#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
。
<sec_api/stdlib_s.h>
中还缺少其他几个 C++ 模板函数,大概是由于缺乏需要,而缺少 getenv_s
的声明可能只是没有人需要的东西 getenv
工作得很好。
值得一提的是 a Windows-only function called _dupenv_s
比 getenv_s
更容易使用,您只需使用标准 free
函数释放内存即可。它在 <sec_api/stdlib_s.h>
中声明,因此您可以毫无问题地使用它。
修改原答案:
在回答这个问题时,从源代码构建的 MinGW-w64 允许您默认启用或禁用安全 CRT 函数的公开,但即使启用,它似乎也没有将大多数标准 C 函数标记为安全替换为 "deprecated",就像 Visual C++ 的 CRT header 所做的那样(实际上,它似乎确实将其中一些标记为已弃用,但宏在我正在使用的构建中扩展为空) .
为了更直接地解决这个问题,MinGW-w64 实现目前将安全 CRT 函数的原型存储在 sec_api
目录中的单独 header 文件中,并且 header 文件不包含在标准 C header 中,这意味着相应的 C++ header <cstdlib>
也不会声明函数,因为它仅包含标准 header.
相反,您需要显式包含所需的 C header,例如 <sec_api/stdlib_s.h>
、<sec_api/stdio_s.h>
等,如果安全 API 已启用(即 MINGW_HAS_SECURE_API
在 _mingw.h
中定义为 1)。由于函数可能可用于链接,您可以在任何包含之前使用 #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
);
已宣布并实施。
基于 examples in Microsoft's documentation 和 MinGW-w64 情况下的预处理器输出,两种实现都将安全函数放在全局 C++ 命名空间中,而不是 std
命名空间(例如 strcpy_s
其完全限定形式是 ::strcpy_s
),因为它们不是标准的 C++ 函数。
根据 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++ 似乎没有暴露微软 ucrt 的 C11 getenv_s?
在 c++ 中,我们是否已经有了 可移植 安全检索环境变量的方法?
In c++, do we already have a portable way to retrieve environment variables safely?
您可以使用 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
是对 C 中 getenv
的改进,您需要以某种方式处理空指针和字符串长度,而在 C++ 中,我们有不同的解决方案(std::string
用于可变长度字符串和 std::optional
可选值)。
编辑:
下面最初修改的答案并不完全正确。目前在 MinGW-w64 实现上 <sec_api/stdlib_s.h>
中没有 getenv_s
的声明,但是你可以自己声明:
#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
。
<sec_api/stdlib_s.h>
中还缺少其他几个 C++ 模板函数,大概是由于缺乏需要,而缺少 getenv_s
的声明可能只是没有人需要的东西 getenv
工作得很好。
值得一提的是 a Windows-only function called _dupenv_s
比 getenv_s
更容易使用,您只需使用标准 free
函数释放内存即可。它在 <sec_api/stdlib_s.h>
中声明,因此您可以毫无问题地使用它。
修改原答案:
在回答这个问题时,从源代码构建的 MinGW-w64 允许您默认启用或禁用安全 CRT 函数的公开,但即使启用,它似乎也没有将大多数标准 C 函数标记为安全替换为 "deprecated",就像 Visual C++ 的 CRT header 所做的那样(实际上,它似乎确实将其中一些标记为已弃用,但宏在我正在使用的构建中扩展为空) .
为了更直接地解决这个问题,MinGW-w64 实现目前将安全 CRT 函数的原型存储在 sec_api
目录中的单独 header 文件中,并且 header 文件不包含在标准 C header 中,这意味着相应的 C++ header <cstdlib>
也不会声明函数,因为它仅包含标准 header.
相反,您需要显式包含所需的 C header,例如 <sec_api/stdlib_s.h>
、<sec_api/stdio_s.h>
等,如果安全 API 已启用(即 MINGW_HAS_SECURE_API
在 _mingw.h
中定义为 1)。由于函数可能可用于链接,您可以在任何包含之前使用 #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
);
已宣布并实施。
基于 examples in Microsoft's documentation 和 MinGW-w64 情况下的预处理器输出,两种实现都将安全函数放在全局 C++ 命名空间中,而不是 std
命名空间(例如 strcpy_s
其完全限定形式是 ::strcpy_s
),因为它们不是标准的 C++ 函数。