上記のコードでVSデバッガーの問題が発生しました:
class Animal {
public:
};
class Stupid {
public:
};
class Dog : public Stupid, public Animal {
public:
};
int main() {
std::unique_ptr<Animal> animal = std::unique_ptr<Dog>(new Dog());
animal.reset();
return 0;
}
このコードは、「ntdl.dll」と「wntdll.pdb」を含む「animal.reset()」を実行した後にエラーをスローします。
「ignore」を複数回(3)回押した場合に、MSVCランタイムライブラリによってアサーションエラーが発生した式は次のとおりです。
1- _CrtIsValidHeapPointer(block)
2- is_block_type_valid(header->_block_use)
3- HEAP CORRUPTION DETECTED: before Free block (#-50331640) at 0x03737E21. CRT detected that the application wrote to memory before start of heap buffer.
しかし、Dogの継承順序を次のように変更すると、次のようになります。
class Dog : public Animal, public Stupid {
public:
};
コードは正常に実行されます。
このエラーはVisualStudio 2017でのみ発生し、Android StudioのIdeoneで試しましたが、継承の順序に関係なく正常に動作します。
渡したポインタがdelete
から戻ってきたものと同じではないため、これは壊れますnew
。
アップキャストとは、基本的に、派生へのポインタを取得し、それがベースへのポインタであると偽ることを意味します。単一継承の場合、これは正しく機能します。これは、ベース部分が常に派生オブジェクトに格納される最初のものであるためです。しかし、多重継承では、2つの基盤があります!
したがって、2塁にアップキャストするときは、実際にポインターの値を変更して、ポインターが指しているものが実際にオブジェクトのそれぞれのベース部分になるようにする必要があります。デバッガーでポインターの値を調べることにより、次のことを確認できます。
Dog* d = new Dog;
Animal* a = d;
a
ポインタは、後ろに1つのバイトを指しますd
ポインタ。
すでに述べたように、これは、削除呼び出しで使用している基本クラスタイプに仮想デストラクタを追加することで修正できます(Animal
例では)。これにより、コンパイラはポインタをに渡す前にポインタを正しく再調整するための追加のコードを生成しdelete
ます。
gccは実際にここで空ベースクラスの最適化を実装しているため、この例はそこで機能することに注意してください。両方の拠点は同じオフセットに住んでいます。非静的データメンバーを基本クラスに追加し始めるとすぐに、そこで壊れ始めます。
この記事はインターネットから収集されたものであり、転載の際にはソースを示してください。
侵害の場合は、連絡してください[email protected]
コメントを追加