@Author:CSU张扬
@Email:csuzhangyang@gmail.com or csuzhangyang@qq.com
@我的网站: https://www.faker.top
Invalid address specified to RtlValidateHeap
1. 问题概述
报错如下:
HEAP[String.exe]: Invalid address specified to RtlValidateHeap( 02730000, 0274ED98 )
监视窗口各变量的值:
异常位置发生在 v.push_back(std::move(s2));
,该语句进入了 free()
函数, 异常最后在函数 free()
的最后。free()
是我自定义的 String
类的析构函数内容,释放 allocator
分配的内存。
class String {
public:
// 省略一部分代码。。。
// 正确的代码
String(String&& s) noexcept : sz(s.sz), p(s.p) {
s.p = 0;
s.sz = 0;
std::cout << "move constructor" << std::endl;
}
// 错误的代码
// String(String&& s) noexcept : sz(s.sz), p(s.p) {
// s.free();
// std::cout << "move constructor" << std::endl;
// }
String& operator=(String&&) noexcept;
~String() { free(); }
private:
void free();
static std::allocator<char> alloc;
char *p;
size_t sz;
};
void String::free() {
if (p) {
std::for_each(begin(), end(),
[](const char& ptr) { alloc.destroy(&ptr); });
// for (auto ptr = end(); ptr != begin();)
// alloc.destroy(--ptr);
alloc.deallocate(p, sz);
}
}
/* 主函数 */
int main() {
String s1("one"), s2("two");
String s3 = s1;
s3 = s2;
cout << "create an empty vector" << endl;
vector<String> v;
cout << "----v.reserve(5)----" << endl;
v.reserve(5);
cout << "----v.push_back(s1);----" << endl;
v.push_back(s1);
cout << "----v.push_back(std::move(s2));----" << endl;
// 不会调用拷贝构造函数
v.push_back(std::move(s2)); /* 异常位置 */
cout << "----v.push_back(String(\"three\"));----" << endl;
v.push_back(String("three"));
cout << "----v.push_back(\"four\");----" << endl;
// 调用const char*的构造函数生成一个临时量,再调用拷贝构造函数。
v.push_back("four");
}
2. 解决思路
这其实是一段测试 移动构造函数 的代码,错误信息的字面意思就是 为RtlValidateHeap指定的地址无效。
- 看监视窗口的变量值,
p
字符串中的字符无效,初步认为是指针释放的错误。 free()
函数最后一句alloc.deallocate(p, sz)
正是释放内存,那么原因基本就确定下来了。std::move(s2)
会调用移动构造函数,那么可能是移动构造函数出现了问题。- 之前写的错误的代码,我是想直接将右侧对象给释放掉。但是这么做是不对的,C++要求移后源必须处于可析构状态,那么我这么做就会导致它释放了两次,从而产生错误。
3. 解决办法
正确的做法是将右侧对象的指针置为 nullptr
,其他内置类型置为初始值即可。
正确的输出结果如下:
const char*p constructor
const char*p constructor
copy constructor
copy assignment
create an empty vector
----v.reserve(5)----
----v.push_back(s1);----
copy constructor
----v.push_back(std::move(s2));----
move constructor
----v.push_back(String("three"));----
const char*p constructor
move constructor
----v.push_back("four");----
const char*p constructor
move constructor
来源:CSDN
作者:神奇小海螺
链接:https://blog.csdn.net/qq_36408085/article/details/104141621