以下会导致内存问题吗?

时间:2011-01-10 07:13:05

标签: c++ dll

假设我在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解决方案

由于

5 个答案:

答案 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 :)

不是更好吗?