[英]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.