簡體   English   中英

MinGW-w64 g ++是否公開Microsoft ucrt對C11`getenv_s`函數的實現? 如果是,將包含什么標題?

[英]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 ++報告cstdlibstdlib.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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM