删除由placement new创建的变异派生模板类实例

时间:2014-05-20 13:25:23

标签: c++ visual-studio-2010

对于反序列化过程,我编写了一个基类,它根据序列化数据变异为派生类。为实现这一目标,我正在使用placement new运算符。一切正常,直到我尝试删除实例。我尝试了不同的方法,但每次都会出现堆损坏错误。我创建了一个简化的示例代码,显示了我的方法。

我正在使用Visual Studio 2010。

以下是展示问题的小样本代码:

Header.h

#pragma once

#include <type_traits>

class BaseClass
{
private:
    int _someValue;

    BaseClass(const BaseClass &other); // remove copy constructor
    BaseClass(BaseClass &&other); // remove move constructor
    BaseClass &operator=(const BaseClass &other); // remove assignment operator

public:
    BaseClass(void);
    virtual ~BaseClass(void);

    void ChangeType(bool b);
};

template<typename T>
class DerivedClass : public BaseClass
{
private:
    T _someMoreData;

    DerivedClass(const DerivedClass &other); // remove copy constructor
    DerivedClass(DerivedClass &&other); // remove move constructor
    DerivedClass &operator=(const DerivedClass &other); // remove assignment operator

public:
    DerivedClass(void) :
      _someMoreData(0)
    {
        static_assert(std::is_same<T, int>::value || std::is_same<T, long>::value, "DerivedClass must be used with 'int' or 'long'.");
    }

    virtual ~DerivedClass(void)
    {}
};

Source.cpp

#include <stdio.h>
#include <memory>
#include <tchar.h>
#include "Header.h"

BaseClass::BaseClass() :
    _someValue(0)
{}

BaseClass::~BaseClass()
{}

void BaseClass::ChangeType(bool b)
{
    this->~BaseClass();
    if (b)
        new (this) DerivedClass<int>();
    else
        new (this) DerivedClass<long>();
}

int _tmain(int argc, _TCHAR* argv[])
{
    BaseClass *pBC = new BaseClass();
    DerivedClass<int> *pDC = nullptr;

    pBC->ChangeType(true);
    pDC = reinterpret_cast<DerivedClass<int> *>(pBC);

    // work with pDC ...

    // 1st try:
    delete pBC; // ERROR: Heap Corruption

    // 2nd try:
    pBC->~BaseClass(); 
    ::operator delete(pBC); // ERROR: Heap Corruption

    // 3rd try:
    pDC->~DerivedClass();
    ::operator delete(pDC); // ERROR: Heap Corruption

    return 0;
}

错误讯息:

HEAP CORRUPTION DETECTED: after Normal block (#111) at 0x004D6970.
CRT detected that the application wrote to memory after end of heap buffer.

我该如何以干净的方式删除这些实例?

0 个答案:

没有答案