以下情况会导致记忆力出现问题吗?

发布于 2024-10-11 08:10:59 字数 563 浏览 1 评论 0原文

假设我在 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 不同的运行时运行,这会导致问题吗?

如果是这样,是否有非 boost、非 c++ 0x 解决方案

谢谢

Say I have the following in a DLL implementation (eg, it would have a cpp file):

class Base
{
protected:
    Something *some;
public:
    virtual void init()
    {
        some = new Something();
    }

    virtual  ~Base()
    {
        delete some;
    }

};

Then in my exe I make:

class Derived : public Base
{
public:
    virtual void init()
    {
        some = new SomethingElse();
    }
};

int main()
{
   Base *blah = new Derived;
   delete blah;
}

Would this ever cause problems if the DLL is ran with a different runtime than the exe?

if so, is there a non boost, non c++ 0x solution

Thanks

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

凤舞天涯 2024-10-18 08:11:00

我认为你需要像这样编写 ~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* 函数的内存管理


编辑:

更好的是要再添加一个虚拟函数,例如 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!
    }
};

I think you need to write ~Derive() like this

~Derived()
{
   delete some;
   some = 0; //this is must; so that `delete some` in ~Base() works perfectly; 
  //note `delete (void*)0` is fine in C++!
}

Explanation :

Why you need to write this even though the ~Base() does the same thing (it looks it does the same thing) is because ~Derived() ensures that you delete your object from the same heap/memory-pool/etc they were created on.

See these topics:

How to use a class in DLL?
Memory Management with returning char* function


EDIT:

Better would be to add one more virtual function, say deinit(), (a counter-part of your virtual void init()) , redefine this too when you redefine init(), and do the de-allocation there in 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!
    }
};
夏の忆 2024-10-18 08:11:00

Derived 分配了 some,因此它保留了释放它的责任。覆盖析构函数...

如果您始终遵循该原则,那么您的内存处理会简单得多。

Derived allocated some, thus it maintains the responsibility to deallocate it. Overwrite the destructor...

If you always follow that principle, then your memory handling is much simpler.

后知后觉 2024-10-18 08:11:00

不会有任何问题,但显然 Derived 中包含的代码永远不会传递到其他可执行文件。

如果 Something 派生自 SomethingElse 并且具有虚拟析构函数,Base 的析构函数将正确删除 some

There won't be any problems, though obviously the code contained in Derived won't ever make it across to the other executable.

The destructor for Base will correctly delete some provided Something derives from SomethingElse and has a virtual destructor.

九厘米的零° 2024-10-18 08:11:00

我认为你应该在它的构造函数中初始化一些东西。

否则析构函数将随机删除一块内存。

Base::Base()
    : Something(NULL)
{ } 

I think you should initialize something in its constructor.

Otherwise the destructor will delete a random piece of memory.

Base::Base()
    : Something(NULL)
{ } 
沫离伤花 2024-10-18 08:11:00

由于 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 :)

不是更好吗?

It's ugly code because of the protected variable.

I propose we reshape it up. First, let's make sure that all the ownership logic is insulated, so that it is easier to prove right.

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(); }
};

It's only a first step though, because you should not try to manipulate resources directly, you're only going to leak them. So now, we take our shiny interface and reshape the implementation:

// 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 :)

Isn't it much better ?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文