@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
本文深入探讨了C++中移动构造函数的正确使用方法及内存管理问题,通过一个具体的String类实例,分析了在移动语义下如何避免重复释放内存导致的异常,并给出了正确的实现方式。
607

被折叠的 条评论
为什么被折叠?



