Будет ли следующее вызывать проблемы с памятью? - PullRequest
4 голосов
/ 10 января 2011

Скажем, у меня есть следующее в реализации 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;
}

Будет ли это когда-нибудь вызывать проблемы, если DLL будет работать с другой средой выполнения, нежели exe?

если так, есть ли решение без повышения, не с ++ 0x

Спасибо

Ответы [ 5 ]

3 голосов
/ 10 января 2011

Я думаю, вам нужно написать ~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() гарантирует , что вы удаляете объект из того же кучи / пула памяти / и т. д., в котором они были созданы.

Смотрите эти темы:

Как использовать класс в DLL?
Управление памятью с функцией возврата char *


EDIT:

Лучше было бы добавить еще одну виртуальную функцию, скажем, deinit(), (противоположность вашей virtual void init()), переопределить это тоже, когда вы переопределяете init(), и выполнить перераспределение там в 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!
    }
};
0 голосов
/ 10 января 2011

Это ужасный код из-за переменной 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 :)

Разве это не намного лучше?

0 голосов
/ 10 января 2011

Я думаю, вы должны инициализировать что-то в его конструкторе.

В противном случае деструктор удалит случайный фрагмент памяти.

Base::Base()
    : Something(NULL)
{ } 
0 голосов
/ 10 января 2011

Проблем не будет, хотя, очевидно, код, содержащийся в Derived, никогда не попадет на другой исполняемый файл.

Деструктор для Base правильно удалит some при условии, что Something происходит от SomethingElse и имеет виртуальный деструктор.

0 голосов
/ 10 января 2011

Derived выделено some, таким образом, оно сохраняет ответственность за его освобождение.Перезаписать деструктор ...

Если вы всегда следуете этому принципу, то обработка вашей памяти будет намного проще.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...