假设我在DLL实现中有以下内容(例如,它将有一个cpp文件):
class Base
{
protected:
Something *some;
public:
virtual void init()
{
some = new Something();
}
virtual ~Base()
{
delete some;
}
};
然后在我的exe中我做了:
class Derived : public Base
{
public:
virtual void init()
{
some = new SomethingElse();
}
};
int main()
{
Base *blah = new Derived;
delete blah;
}
如果使用与exe不同的运行时运行DLL会不会导致问题?
如果是的话,是否存在非增强,非c ++ 0x解决方案
由于
答案 0 :(得分:3)
我认为你需要像这样写~Derive()
~Derived()
{
delete some;
some = 0; //this is must; so that `delete some` in ~Base() works perfectly;
//note `delete (void*)0` is fine in C++!
}
说明:
为什么你需要写这个,即使~Base()
做同样的事情(看起来它做同样的事情)是因为~Derived()
确保你从你创建的相同堆/内存池/等中删除你的对象。
请参阅以下主题:
How to use a class in DLL?
Memory Management with returning char* function
最好再添加一个虚拟函数,比如deinit()
,(virtual void init()
的一个对应部分),重新定义init()
时再重新定义,并执行de - deinit()
中的分配。
//DLL
class Base
{
protected:
Something *some;
public:
virtual void init()
{
some = new Something();
}
virtual void deinit()
{
delete some;
}
virtual ~Base() { deinit(); }
};
//EXE
class Derived : public Base
{
public:
virtual void init()
{
some = new SomethingElse();
}
virtual void deinit()
{
delete some; //some=0 is not needed anymore!
}
};
答案 1 :(得分:0)
Derived
分配了some
,因此它保留了解除分配的责任。覆盖析构函数......
如果你始终遵循这个原则,那么你的记忆处理就会简单得多。
答案 2 :(得分:0)
不会出现任何问题,但Derived
中包含的代码显然不会覆盖其他可执行文件。
Base
的析构函数将正确删除some
Something
派生自SomethingElse
并具有虚拟析构函数。
答案 3 :(得分:0)
我认为你应该在它的构造函数中初始化一些东西。
否则析构函数将删除随机内存。
Base::Base()
: Something(NULL)
{ }
答案 4 :(得分:0)
由于protected
变量,这是丑陋的代码。
我建议我们重新塑造它。首先,让我们确保所有的所有权逻辑都是绝缘的,以便更容易证明是正确的。
class Base
{
public:
Base(): some(0) {} // better initialize it...
virtual ~Base() { delete some; }
void init() { delete some; some = this->initImpl(); }
private:
Base(Base const&); // no copy
Base& operator=(Base const&); // no assignment
virtual SomeType* initImpl() { return new SomeType(); }
SomeType* some;
}; // class Base
class Derived: public Base
{
virtual SomeOtherType* initImpl() { return new SomeOtherType(); }
};
这只是第一步,因为你不应该试图直接操纵资源,你只会泄漏它们。所以现在,我们采用闪亮的界面并重塑实现:
// something that you should definitely have for your base classes
class noncopyable { protected: noncopyable() {} private: noncopyable(noncopyable const&); noncopyable& operator=(noncopyable const&); };
class Base: noncopyable
{
public:
Base() {}
virtual ~Base() {}
void init() { some.reset(this->initImpl()); }
private:
virtual SomeType* initImpl() { return new SomeType(); }
std::auto_ptr<SomeType> some;
}; // class Base
// same Derived class, that's the beauty of insulation :)
不是更好吗?