我想"%LOCALAPPDATA%/test.txt"用 Windows 環境路徑擴展字串 ( )。下面的函式原則上可以完成這項作業,但是使用相同的輸出字串再次呼叫它(或在呼叫函式之前為輸出字串分配一些值)會產生段錯誤。
顯然,通過轉換char*為std::string,我犯了一些(可能非常糟糕)的錯誤,但我真的不明白這里發生了什么(除了一些記憶體地址稍后不可用的事實)。
#include "processenv.h"
void expandWindowsString(const std::string &input, std::string &output)
{
const char* in = input.c_str();
char* out;
ExpandEnvironmentStrings(in, out, 1024);
output = out;
}
int main(int argc, char *argv[])
{
std::string path;
expandWindowsString("%LOCALAPPDATA%/test.txt", path);
std::cout << "path is " << path << std::endl;
//works fine so far, but if I execute the function again (with 'path') or initialising path beforehand with std::string path = "", a segfault occurs.
expandWindowsString("%LOCALAPPDATA%/test.txt", path); // commenting out this line, makes the code work.
std::cout << "path is " << path << "\n";
}
uj5u.com熱心網友回復:
正如檔案解釋的那樣:
lpDst一個指向緩沖區的指標,該緩沖區接收在lpSrc緩沖區中展開環境變數字串的結果。
緩沖區需要由呼叫者提供,而代碼只是傳遞一個未初始化的指標,同時誘使系統相信它指向大小為 1024 位元組的記憶體。
一個簡單的解決方法是:
void expandWindowsString(const std::string &input, std::string &output)
{
const char* in = input.c_str();
char out[1024];
ExpandEnvironmentStrings(in, out, 1024);
output = out;
}
有很多改進的空間,例如
- 使用Unicode 版本
- 處理錯誤(如檔案中所述)
- 如果 API 呼叫回傳的值大于提供的緩沖區長度,則重復增加輸出緩沖區
std::string使用指標和長度構造 a- 回傳值而不是使用輸出引數
至于為什么第二次呼叫它會失敗:這是一個毫無意義的問題。該代碼通過寫入未初始化的指標表現出未定義的行為。這樣,任何結果都是可能的,包括代碼似乎按預期作業。
uj5u.com熱心網友回復:
ExpandEnvironmentStrings 需要一個已經分配的緩沖區。如果傳遞的緩沖區大小太小而無法容納字串,例如 0,則可以確定緩沖區的大小。
因此,這里有兩個版本,UNICODE 和 ANSI,它們將動態計算大小:
std::wstring expandWindowsString(const std::wstring& input)
{
std::wstring output;
do
{
auto size = ExpandEnvironmentStringsW(input.c_str(), (LPWSTR)output.c_str(), output.size());
if (!size || size <= output.size())
break;
output.resize(size);
} while (true);
output = output.c_str();
return output;
}
std::string expandWindowsString(const std::string& input)
{
std::string output;
do
{
auto size = ExpandEnvironmentStringsA(input.c_str(), (LPSTR)output.c_str(), output.size());
if (!size || size <= output.size())
break;
output.resize(size);
} while (true);
output = output.c_str();
return output;
}
uj5u.com熱心網友回復:
如果您閱讀檔案
lpDst一個指向緩沖區的指標,該緩沖區接收在 lpSrc 緩沖區中展開環境變數字串的結果。請注意,此緩沖區不能與 lpSrc 緩沖區相同。
nSizelpDst 引數指向的緩沖區中可以存盤的最大字符數。使用 ANSI 字串時,緩沖區大小應為字串長度加上終止空字符再加一。使用 Unicode 字串時,緩沖區大小應為字串長度加上終止的空字符。
你會看到你傳遞了無效的引數,你必須提供buffer,所以:
void expandWindowsString(const std::string &input, std::string &output)
{
char out[1024];
ExpandEnvironmentStrings(input.c_str(), out, sizeof (out));
output = out;
}
或避免輸出引數:
std::string expandWindowsString(const std::string &input)
{
char out[1024];
ExpandEnvironmentStrings(input.c_str(), out, sizeof (out));
return out;
}
請注意,您可能應該檢查ExpandEnvironmentStrings.
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/314751.html
上一篇:創建支持基于范圍迭代的COM指標
下一篇:如何在代碼中映射域上的網路驅動器
