我试图建立一个非常简约的存储器读图书馆阅读一些unsigned ints出来。然而,我碰上当ReadUnsignedInt方法要返回一个“堆损坏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;
}
有帮助吗?

解决方案

迈克尔和纳文兼得发现在你的代码相同的主要缺陷,但不是唯一的瑕疵。

shared_ptrdelete被指向在对象时其引用计数变为零。

这意味着你只能给它通过物体分配new - 不new[]

您可能希望使用shared_ptr<vector<byte> > boost::shared_array<byte> 代替。

其他提示

的问题是:

new byte(numberOfBytes)

此分配具有numberOfBytes的值的单个字节。

您想要做的:

new byte[numberOfBytes]    

哪些分配字节numberOfBytes阵列长。

但既然你知道你只是读取4个字节,何苦在所有分配的内存?只是通过一个无符号整型的地址压入堆栈。

你的代码的基本问题已经指出了。看着它,我在想为什么你会在这里都使用一个shared_ptr,虽然。如果我这样做,我可能会使用这样的:

unsigned Memory::ReadUnsignedInt(unsigned address) { 
    unsigned ret;
    ReadProcessMemory(m_hProcess.get(), (void *)address, &ret, sizeof(ret), NULL);
    return ret;
}

std::vector<char> Memory::ReadBytes(unsigned address, int num) { 
    std::vector<char> ret(num);
    ReadProcessMemory(m_hProcess.get(), (void *)address, &ret[0], num, NULL);
    return ret;
}

然后再次,代替ReadUnsignedInt,我会倾向于使用模板:

template <class T>
T Memory::Read(unsigned address) { 
    T ret;
    ReadProcessMemory(m_hProcess.get(), (void*)address, &ret, sizeof(ret), NULL);
    return ret;
}

由于您没有通过从中可以推断为模板参数类型的参数,你总是必须明确指定:

int x = Read<int>(wherever);
char a = Read<char>(wherever);

在替代方案是通过所述目的地作为一个参数:

template <class T>
Memory::Read(unsigned address, T &t) { 
    ReadProcessMemory(my_hProcess.get(), (void *)address, &t, sizeof(t), NULL);
};

其中你使用像:

Read(wherever, some_int);
Read(somewhere, some_long);

等。

如果你担心返回字符的载体的效率低下,你可能不应该 - VC ++(像其他大多数较新的编译器)有什么叫做“命名返回值优化”,这意味着在一个情况这样,它通过一个隐藏的参考分配结果的向量,并会的ReadBytes用它来存放数据直接到哪里去无论如何收场。对于这个问题,有任何合理的优化开启所有,的ReadBytes几乎肯定会最终成为内联函数,所以没有什么真正参与被“通过”或“返回”可言。

在另一方面,该代码将不会与旧的编译工作特别好 - 与旧足够的编译器,使用成员模板函数的版本甚至可能不会编译。只要您使用的是较新的编译器,但是,生活应该是不错的。

相信new byte(numberOfBytes)应当new byte[numberOfBytes]。否则,你会只分配了一个字节。刚刚完成了答案,因为@ephemient表明您不能使用的shared_ptr在这里,因为它会做一个delete这里,你应该做的delete[]。如果不这样做,该行为将是不确定的。

scroll top