Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 以下情况是否会导致内存问题?_C++_Dll - Fatal编程技术网

C++ 以下情况是否会导致内存问题?

C++ 以下情况是否会导致内存问题?,c++,dll,C++,Dll,假设我在DLL实现中有以下内容(例如,它将有一个cpp文件): 然后在我的exe中,我制作: class Derived : public Base { public: virtual void init() { some = new SomethingElse(); } }; int main() { Base *blah = new Derived; delete blah; } 如果DLL使用与exe不同的运行时运行,这会导致问题吗

假设我在DLL实现中有以下内容(例如,它将有一个cpp文件):

然后在我的exe中,我制作:

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

int main()
{
   Base *blah = new Derived;
   delete blah;
}
如果DLL使用与exe不同的运行时运行,这会导致问题吗

如果是,有没有非增强型非C++ 0x解决方案< /P>


感谢

派生的
分配的部分,因此它保留解除分配的责任。覆盖析构函数


如果您总是遵循这个原则,那么您的内存处理就会简单得多。

我认为您需要像这样编写
~derivate()

~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()
确保您从创建对象的堆/内存池/等中删除对象

请参见以下主题:



编辑: 最好再添加一个虚拟函数,比如说
deinit()
,(您的
虚拟void init()
的计数器部分),在重新定义
init()
时也重新定义这个函数,并在
deinit()中执行反分配


这不会有任何问题,尽管
派生的
中包含的代码显然不会传递给其他可执行文件


Base
的析构函数将正确删除
some
,前提是
SomethingElse
派生自
SomethingElse
,并具有虚拟析构函数。

我认为您应该在其构造函数中初始化某些内容

否则,析构函数将删除一段随机内存

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

这是一个丑陋的代码,因为
受保护的
变量

我建议我们把它改造一下。首先,让我们确保所有的所有权逻辑都是隔离的,这样更容易证明是正确的

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 :)
//基类中应该有一些东西
类noncopyable{protected:noncopyable(){}private:noncopyable(noncopyable const&);noncopyable&operator=(noncopyable const&);};
类基:不可复制
{
公众:
Base(){}
虚拟~Base(){}
void init(){some.reset(this->initImpl());}
私人:
虚拟SomeType*initImpl(){返回新的SomeType();}
std::自动检查一些;
}; // 阶级基础
//相同的派生类,这就是绝缘的美妙之处:)

这不是更好吗?

@Milo:为什么你不重写析构函数来删除
SomethingElse
?@user384706我想基类析构函数会处理它?@user384706基类析构函数删除
一些
,并正确地声明为虚拟,所以他不需要。什么是“与exe不同的运行时”? 使用不同的编译器编译exe和dll?@Shelwien-在windows中,您可以将c运行时直接编译到链接到的各种库中。这会导致每个DLL都有自己的堆管理器的问题。Windows使用堆来实现免费存储。因此,在程序的某个部分中的免费存储上创建的元素必须被程序的同一部分删除(exe与DLL等),否则您将删除堆管理器从未创建过的内容,然后爆炸!!!这是一个巨大的麻烦,给那些做这件事的人带来了无尽的痛苦。但是如果我不这样做,会发生什么?删除空(0)指针会被忽略-删除有效指针两次可能会导致崩溃,这取决于您的操作系统有多脆弱。在正常情况下,DLL将使用与应用程序相同的堆。只有在明确创建自己的堆或针对运行时进行静态链接(MS特别建议不要这样做)的情况下,才会有seprate堆。大约10年前,当静态地将DLL链接到运行时是标准过程时,这个建议是正确的。如果他删除
派生
的析构函数中的
部分
,则
析构函数将立即被调用,并再次尝试删除
部分
,从而产生未定义的行为(除非您采取Nawaz所做的预防措施,并在删除后将其设置为
NULL
)为什么一个C++库的实现是“代码”>删除< /代码>优雅地释放另一个代码<新的< /代码>分配的内存?好运链接到来自不同编译器的C++ DLL -名字的Mangle会破坏你,这就是为什么<代码>使用了
——如果您使用的是同一个编译器,那么就没有理由或借口使用不同的分配器。如果您仍然能够实现它,是的,它可能会崩溃。问题没有明确说明这是重要的部分。。。
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 :)