问题不是由于缓冲区溢出,而是您根本没有对wchar[]
要添加到过滤器的字符串进行空终止。
根据cppreference.com 上的std::basic_string::copy()
文档:
将子字符串复制[pos, pos+count)
到 指向的字符串dest
。如果请求的子字符串持续到字符串的末尾,或者如果count == npos
,则复制的子字符串是[pos, size())
。结果字符串不是以空值结尾的。
因此,您需要将这些空终止符添加到您的字符串中,例如:
COMDLG_FILTERSPEC* CreateFILTERSPEC(const std::list<std::pair<std::wstring, std::wstring>> &_filters) {
COMDLG_FILTERSPEC* filterSpecs = new COMDLG_FILTERSPEC[_filters.size()];
COMDLG_FILTERSPEC* filterSpec = filterSpecs;
for (const 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 !
filterSpec->pszName = f1_p;
filterSpec->pszSpec = f2_p;
++filterSpec;
}
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;
或者,您可以将所有new[]
'ed 内存合并到一个分配中以便于清理,例如:
COMDLG_FILTERSPEC* CreateFILTERSPEC(const std::list<std::pair<std::wstring, std::wstring>> &_filters) {
size_t size = sizeof(COMDLG_FILTERSPEC) * _filters.size();
for (const auto &filter : _filters) {
size += (filter.first.length() + filter.second.length() + 2);
}
COMDLG_FILTERSPEC* filterSpecs = reinterpret_cast<COMDLG_FILTERSPEC*>(new BYTE[size]);
COMDLG_FILTERSPEC* filterSpec = filterSpecs;
wchar_t *strData = reinterpret_cast<wchar_t*>(filterSpecs + _filters.size());
for (const auto &filter : _filters) {
filterSpec->pszName = strData;
filter.first.copy(strData, filter.first.length());
strData += filter.first.length();
*strData++ = L'\0';
filterSpec->pszSpec = strData;
filter.second.copy(strData, filter.second.length());
strData += filter.second.length();
*strData++ = L'\0';
++filterSpec;
}
return filterSpecs;
}
COMDLG_FILTERSPEC *filterSpecs = CreateFILTERSPEC(filters);
// use filterSpecs as needed ...
delete[] reinterpret_cast<BYTE*>(filterSpecs);
但是,如果 的内容std::list
将持续超过 的生命周期COMDLG_FILTERSPEC
,那么您根本不需要new[]
任何内存来存储字符串,只需std::wstring
按原样使用现有内存,例如:
COMDLG_FILTERSPEC * CreateFILTERSPEC(const std::list<std::pair<std::wstring, std::wstring>> &_filters) {
COMDLG_FILTERSPEC* filterSpecs = new COMDLG_FILTERSPEC[_filters.size()];
COMDLG_FILTERSPEC* filterSpec = filterSpecs;
for (const auto &filter : _filters) {
filterSpec->pszName = filter.first.c_str();
filterSpec->pszSpec = filter.second.c_str();
++filterSpec;
}
return filterSpecs;
}
COMDLG_FILTERSPEC *filterSpecs = CreateFILTERSPEC(filters);
// use filterSpecs as needed ...
delete[] filterSpecs;
在这种情况下,您应该考虑返回 astd::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());
COMDLG_FILTERSPEC* filterSpec = filterSpecs.get();
for (const auto &filter : _filters) {
filterSpec->pszName = filter.first.c_str();
filterSpec->pszSpec = filter.second.c_str();
++filterSpec;
}
return filterSpecs;
}
auto filterSpecs = CreateFILTERSPEC(filters);
// use filterSpecs.get() as needed ...
// the COMDLG_FILTERSPEC memory is freed automatically when
// filterSpecs goes out of scope...
或者,返回 a std::vector
,例如:
std::vector<COMDLG_FILTERSPEC> CreateFILTERSPEC(const std::list<std::pair<std::wstring, std::wstring>> &_filters) {
std::vector<COMDLG_FILTERSPEC> filterSpecs(_filters.size());
COMDLG_FILTERSPEC* filterSpec = filterSpecs.data();
for (const auto &filter : _filters) {
filterSpec->pszName = filter.first.c_str();
filterSpec->pszSpec = filter.second.c_str();
++filterSpec;
}
return filterSpecs;
}
auto filterSpecs = CreateFILTERSPEC(filters);
// use filterSpecs.data() as needed ...
// the COMDLG_FILTERSPEC memory is freed automatically when
// filterSpecs goes out of scope...