如何修复堆损坏
我尝试构建一个非常简约的内存读取库来从中读取一些unsigned int
。但是,当 ReadUnsignedInt 方法想要返回时,我遇到了“HEAP CORRUPTION DETECTED”错误消息。
检测到堆损坏。 CRT 检测到应用程序在缓冲区结束后写入内存。
正如我所读到的,这可能是尝试双重删除某些内容时的原因。这可能是由于 std::tr1::shared_ptr 的某些错误使用造成的,但我无法确定我对它们做错了什么。代码如下(错误处理省略):
unsigned int Memory::ReadUnsignedInt (unsigned int address) const {
std::tr1::shared_ptr<byte> bytes =
this->ReadBytes(address, sizeof(unsigned int));
return *((int*)bytes.get());
// correct value (how to improve this ugly piece of code?)
}
std::tr1::shared_ptr<byte> Memory::ReadBytes (
unsigned int address, int numberOfBytes) const
{
std::tr1::shared_ptr<byte> pBuffer(new byte(numberOfBytes));
ReadProcessMemory(m_hProcess.get(), (LPCVOID)address,
pBuffer.get(), numberOfBytes * sizeof(byte), NULL))
return pBuffer;
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
Michael 和 Naveen 都在您的代码中发现了相同的主要缺陷,但不是唯一的缺陷。
当引用计数为零时,
shared_ptr
将删除
所指向的对象。这意味着您只能给它由
new
分配的对象,而不是new[]
。您可能希望使用
shared_ptr; >
或boost::shared_array< ;byte>
代替。Michael and Naveen have both found the same major flaw in your code, but not the only flaw.
shared_ptr
willdelete
the pointed-at object when its reference count goes to zero.This means you can only give it objects allocated by
new
-- notnew[]
.You may wish to use
shared_ptr<vector<byte> >
orboost::shared_array<byte>
instead.问题是:
这分配了一个值为 numberOfBytes 的单个字节。
您想要执行的操作:
分配一个字节数组 numberOfBytes long。
但既然你知道你只读取 4 个字节,为什么还要费心分配内存呢?只需在堆栈上传递 unsigned int 的地址即可。
The issue is:
This allocates a single byte with a value of numberOfBytes.
You want to do:
Which allocates an array of bytes numberOfBytes long.
But since you know you are only reading 4 bytes, why bother allocating memory at all? Just pass the address of a unsigned int on the stack.
已经指出了代码的基本问题。看着它,我想知道为什么你要在这里使用shared_ptr。如果我这样做,我可能会使用这样的东西:
然后,我会尝试使用模板,而不是 ReadUnsignedInt:
因为您没有传递可以从中推断出模板类型的参数参数,您始终必须显式指定:
另一种方法是将目的地作为参数传递:
您可以使用该参数,例如:
等等。
如果您担心返回 char 向量的效率低下,您可能不应该 - VC++(像大多数其他相当当前的编译器一样)具有所谓的“命名返回值优化”,这意味着在这样的情况下,它传递一个对您将结果分配给的向量的隐藏引用,ReadBytes 将使用该引用将数据直接存放在最终要存放的位置。就此而言,只要打开任何合理的优化,ReadBytes 几乎肯定会最终成为内联函数,因此所涉及的任何内容都不会真正被“传递”或“返回”。
另一方面,这段代码在较旧的编译器中工作得不太好——并且在足够旧的编译器中,使用成员模板函数的版本甚至可能无法编译。然而,只要您使用最新的编译器,生活应该会很好。
The basic problems with your code have been pointed out already. Looking at it, I'm left wondering why you'd use a shared_ptr here at all, though. If I were doing it, I'd probably use something like this:
Then again, instead of ReadUnsignedInt, I'd be tempted to use a template:
Since you don't pass a parameter from which it can deduce the type for the template parameter, you'd always have to specify explicitly:
The alternative would be to pass the destination as a parameter:
which you'd use like:
and so on.
If you're worried about the inefficiency of returning a vector of char, you probably shouldn't -- VC++ (like most other reasonably current compilers) has what's called a "named return value optimization", which means in a situation like this, it passes a hidden reference to the vector you assign the result to, and ReadBytes will use that to deposit the data directly where it's going to end up anyway. For that matter, with any reasonable optimization turned on at all, ReadBytes will almost certainly end up as an inline function, so nothing involved really gets "passed" or "returned" at all.
On the other hand, this code won't work particularly well with older compilers -- and with old enough compilers, the versions using member template functions probably won't even compile. As long as you use a reasonably current compiler, however, life should be good.
我相信
new byte(numberOfBytes)
应该是new byte[numberOfBytes]
。否则,您将只分配一个字节。只是为了完成答案,正如 @ephemient 所指出的,您不能在此处使用shared_ptr,因为它将在您应该执行delete[]
的地方执行delete
操作。如果不这样做,行为将是未定义的。I believe
new byte(numberOfBytes)
should benew byte[numberOfBytes]
. Otherwise you would have allocated only one byte. Just to complete the answer, as @ephemient indicated you can not use shared_ptr here as it will do adelete
where as you should dodelete[]
. If not done like this, the behavior will be undefined.