[英]c++ COM COMDLG_FILTERSPEC array overrun
所以我有這個 function 它將獲取一個字符串對列表並生成一個 COMDLG_FILTERSPEC 數組。 對是這樣的: first = "All Types"
second = "*.*"
function 工作,但是我得到緩沖區溢出,如下所示:
我不知道如何解決這個問題或為什么它會超支。 任何人都可以幫忙嗎?
這是代碼:
COMDLG_FILTERSPEC * CreateFILTERSPEC(std::list<std::pair<std::wstring, std::wstring>> _filters) {
//TODO: Causes memory leak on deletion. Fix it.
COMDLG_FILTERSPEC* filterSpecs = new COMDLG_FILTERSPEC[_filters.size()];
int i = 0;
for (std::pair<std::wstring, std::wstring> filter : _filters) {
PWSTR f1_p = new wchar_t[filter.first.length()];
filter.first.copy(f1_p, filter.first.length());
PWSTR f2_p = new wchar_t[filter.second.length()];
filter.second.copy(f2_p, filter.second.length());
COMDLG_FILTERSPEC fs = { f1_p, f2_p };
filterSpecs[i] = fs;
i++;
}
return filterSpecs;
}
任何幫助表示贊賞,謝謝。
問題不是由於緩沖區溢出,而是您根本沒有對要添加到過濾器的wchar[]
字符串進行空終止。
根據 cppreference.com 上的std::basic_string::copy()
文檔:
將 substring
[pos, pos+count)
復制到dest
指向的字符串。 如果請求的 substring 持續超過字符串的末尾,或者如果count == npos
,則復制的 substring 為[pos, size())
。 結果字符串不是以空值結尾的。
因此,您需要將那些 null 終止符添加到您的字符串中,例如:
COMDLG_FILTERSPEC* CreateFILTERSPEC(std::list<std::pair<std::wstring, std::wstring>> _filters) {
COMDLG_FILTERSPEC* filterSpecs = new COMDLG_FILTERSPEC[_filters.size()];
int i = 0;
for (auto &filter : _filters) {
PWSTR f1_p = new wchar_t[filter.first.length() + 1]; // <-- note the +1 !
filter.first.copy(f1_p, filter.first.length());
f1_p[filter.first.length()] = L'\0'; // <-- add this !
PWSTR f2_p = new wchar_t[filter.second.length() + 1]; // <-- note the +1 !
filter.second.copy(f2_p, filter.second.length());
f2_p[filter.second.length()] = L'\0'; // <-- add this !
COMDLG_FILTERSPEC fs = { f1_p, f2_p };
filterSpecs[i] = fs;
++i;
}
return filterSpecs;
}
COMDLG_FILTERSPEC *filterSpecs = CreateFILTERSPEC(filters);
// use filterSpecs as needed ...
for(int i = 0; i < filters.size(); ++i) {
delete[] filterSpecs[i].pszName;
delete[] filterSpecs[i].pszSpec;
};
delete[] filterSpecs;
如果std::list
的內容將持續超過COMDLG_FILTERSPEC
的生命周期,那么您根本不需要new[]
任何 memory 字符串,只需按原樣使用現有的std::wstring
memory,例如:
COMDLG_FILTERSPEC * CreateFILTERSPEC(const std::list<std::pair<std::wstring, std::wstring>> &_filters) {
COMDLG_FILTERSPEC* filterSpecs = new COMDLG_FILTERSPEC[_filters.size()];
int i = 0;
for (const auto &filter : _filters) {
COMDLG_FILTERSPEC fs = { filter.first.c_str(), filter.second.c_str() };
filterSpecs[i++] = fs;
}
return filterSpecs;
}
COMDLG_FILTERSPEC *filterSpecs = CreateFILTERSPEC(filters);
// use filterSpecs as needed ...
delete[] filterSpecs;
話雖如此,您應該考慮返回std::unique_ptr<COMDLG_FILTERSPEC[]>
而不是原始COMDLG_FILTERSPEC*
指針,例如:
std::unique_ptr<COMDLG_FILTERSPEC[]> CreateFILTERSPEC(const std::list<std::pair<std::wstring, std::wstring>> &_filters) {
auto filterSpecs = std::make_unique<COMDLG_FILTERSPEC[]>(_filters.size());
int i = 0;
for (const auto &filter : _filters) {
COMDLG_FILTERSPEC fs = { ... };
filterSpecs[i++] = fs;
}
return filterSpecs;
}
auto filterSpecs = CreateFILTERSPEC(filters);
// use filterSpecs.get() as needed ...
// the COMDLG_FILTERSPEC memory is freed automatically when
// filterSpecs goes out of scope...
或者,返回一個std::vector
,例如:
std::vector<COMDLG_FILTERSPEC> CreateFILTERSPEC(const std::list<std::pair<std::wstring, std::wstring>> &_filters) {
std::vector<COMDLG_FILTERSPEC> filterSpecs(_filters.size());
int i = 0;
for (const auto &filter : _filters) {
COMDLG_FILTERSPEC fs = { ... };
filterSpecs[i++] = fs;
}
return filterSpecs;
}
auto filterSpecs = CreateFILTERSPEC(filters);
// use filterSpecs.data() as needed ...
// the COMDLG_FILTERSPEC memory is freed automatically when
// filterSpecs goes out of scope...
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.