質問
私はそれのうちいくつかunsigned int
sを読み取るためのライブラリを読んで非常に最小限のメモリを構築しようとしました。 ReadUnsignedInt
メソッドが返すしたい場合しかし、私はに実行し、エラーメッセージを「ヒープの破損が検出された」ます。
私が読んでてきたように、削除何かを倍増しようとすると、ヒープの破損が検出されました。 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;
}
解決
マイケルとのNaveenは、両方があなたのコード内の同じ大きな欠陥を発見しただけでなく、欠陥ます。
shared_ptr
その参照カウントがゼロになったときに尖った-でオブジェクトをdelete
されます。
あなたがオブジェクトのみを与えることができ、この手段はnew
によって割り当てられた - 。ないnew[]
あなたはshared_ptr<vector<byte> >
を使用することをお勧めしますか boost::shared_array<byte>
代わります。
他のヒント
問題があります:
new byte(numberOfBytes)
これはnumberOfBytesの値に1バイトを割り当てます。
あなたがやりたいます:
new byte[numberOfBytes]
長いnumberOfBytesバイトの配列を割り当てます。あなたが唯一の4つのバイトを読んでいる知っているので、
しかし、なぜすべてのメモリを割り当てるわざわざ?ただ、スタック上にunsigned int型のアドレスを渡します。
あなたのコードとの基本的な問題は、すでに指摘されています。それを見て、私はあなたがいますが、すべてではここでの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]
べきであると信じています。そうしないと、1バイトのみを割り当てられているだろう。 @ephemientが、それはあなたがdelete
を行う必要がありますようdelete[]
を行いますと、あなたがここでのshared_ptrを使用することはできません示されているように、単に、答えを完了します。このように行われていない場合、動作は未定義されます。