![](/img/trans.png)
[英]C++ code compiling in minGW-W64 g++ does not compile with Ubuntu g++
[英]Does MinGW-w64 g++ expose microsoft ucrt's implementation of C11 `getenv_s` function? If yes, what header to be included?
根據cppreference.com,自C11起getenv_s得到支持
errno_t getenv_s( size_t *restrict len, char *restrict value,
rsize_t valuesz, const char *restrict name );
在MinGW-w64 8.1中,g ++報告cstdlib
和stdlib.h
#include
錯誤
use of undeclared identifier 'getenv_s'; did you mean '_wgetenv_s'?
errcode = getenv_s(&envsize, NULL, 0, name);
^~~~~~~~
_wgetenv_s
我想知道為什么MinGW-w64 g ++似乎不公開Microsoft ucrt的C11 getenv_s嗎?
在c ++中,我們是否已經有了一種可移植的方法來安全地檢索環境變量?
在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
是對C語言中getenv
的改進,在C語言中您需要以某種方式處理空指針和字符串長度,而在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
聲明了getenv_s
。
<sec_api/stdlib_s.h>
中還缺少其他幾個C ++模板函數,大概是由於缺乏需要,並且完全沒有聲明getenv_s
原因也許就是沒人需要,因為getenv
可以正常工作。
值得一提的是,有一個僅用於Windows的函數_dupenv_s
可以代替getenv_s
更容易使用,並且您只需使用標准的free
函數釋放內存。 它在<sec_api/stdlib_s.h>
,因此您可以毫無問題地使用它。
修改原始答案:
在回答此問題時,默認情況下,從源構建的MinGW-w64允許您啟用或禁用安全CRT功能的公開,但是即使啟用,它似乎也不會將大多數帶有安全替代品的標准C功能標記為“已棄用”。 “ Visual C ++的CRT標頭的方式(實際上,它似乎確實將其中一些標為已棄用,但宏在我正在使用的內部版本中擴展為空)。
為了更直接地解決這個問題,MinGW-w64實現當前將安全CRT功能的原型存儲在sec_api
目錄中的單獨頭文件中,並且該頭文件不包含在標准C頭中,這意味着相應的C ++頭<cstdlib>
也不會聲明函數,因為它僅包含標准頭。
相反,您需要顯式包括所需的C頭文件,例如<sec_api/stdlib_s.h>
, <sec_api/stdio_s.h>
等,它們僅在啟用了安全API的情況下才聲明函數(即MINGW_HAS_SECURE_API
為在_mingw.h
定義為1)。 由於這些函數很可能可用於鏈接,因此您可以在任何包含項之前使用#define MINGW_HAS_SECURE_API 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
);
聲明並實現。
根據微軟的文檔實例中的MinGW-W64的情況和預處理器輸出,既實現將全球C中的安全功能++的命名空間,而不是std
的命名空間(如strcpy_s
在其完全合格的形式是::strcpy_s
),因為它們是不是標准的C ++函數。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.