According to cppreference.com, getenv_s gets supported since C11
errno_t getenv_s( size_t *restrict len, char *restrict value,
rsize_t valuesz, const char *restrict name );
With MinGW-w64 8.1, g++ reports an error with both #include
with cstdlib
and stdlib.h
use of undeclared identifier 'getenv_s'; did you mean '_wgetenv_s'?
errcode = getenv_s(&envsize, NULL, 0, name);
^~~~~~~~
_wgetenv_s
I wonder why MinGW-w64 g++ seems not to expose microsoft ucrt's C11 getenv_s?
In c++, do we already have a portable way to retrieve environment variables safely?
Edit:
The originally amended answer below is not entirely correct. Currently there is no declaration for getenv_s
in <sec_api/stdlib_s.h>
on MinGW-w64 implementations, but you can declare it yourself:
#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
On MSVC, you'd still just use #include <stdlib.h>
as getenv_s
is declared there.
There are also several other C++ template functions missing from the <sec_api/stdlib_s.h>
already, presumably due to lack of need, and the lack of declaration for getenv_s
entirely is perhaps just something nobody needed as getenv
worked just fine.
It's worth mentioning that there is a Windows-only function called _dupenv_s
that is much easier to use in place of getenv_s
, and you'd just free the memory using the standard free
function. It is declared in <sec_api/stdlib_s.h>
, so you can use it without issue.
Amended original answer:
At the time of this answer, MinGW-w64 built from source allows you to enable or disable the exposure of the secure CRT functions by default, but even when enabled, it does not appear to mark most standard C functions with secure replacements as "deprecated" the way that Visual C++'s CRT headers do (actually, it appears that it does mark some of them as deprecated, but the macros expand to nothing in the build I'm using).
To more directly address the question, the MinGW-w64 implementation currently stores the prototypes for the secure CRT functions in a separate header file in the sec_api
directory, and that header file is not included from the standard C header, which means the corresponding C++ header <cstdlib>
will not declare the functions either since it includes only the standard header.
Instead, you need to explicitly include the C headers you need such as <sec_api/stdlib_s.h>
, <sec_api/stdio_s.h>
, etc., which will only declare the functions if the secure API has been enabled (i.e. MINGW_HAS_SECURE_API
is defined to 1 in _mingw.h
). As the functions are likely available for linking, you can just use #define MINGW_HAS_SECURE_API 1
before any includes to enable the use of the secure functions that are declared, or declare the functions yourself in the event that they're undeclared.
I feel it's worth mentioning that many, though not all, of the C++-only template functions such as
// #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
);
are declared and implemented.
Based on examples in Microsoft's documentation and preprocessor output in the case of MinGW-w64, both implementations place the secure functions in the global C++ namespace, not the std
namespace (e.g. strcpy_s
in its fully qualified form is ::strcpy_s
) as they're not standard C++ functions.