【问题标题】:Freeing memory allocated from placement new释放从放置新分配的内存
【发布时间】:2012-04-10 22:25:37
【问题描述】:

考虑以下代码,

#include "iostream"
#include "conio.h"

using namespace std;

class sample
{
      private:
              int i;
      public:
             sample(int ii=0) : i(ii){                         
                   cout<<"Constructing Object"<<endl; 
                   }

             ~sample() { cout<<"Destructing Object"<<endl; }

             void* operator new(size_t nSize, void* loc){
                   cout <<"Inside new"<<endl;
                   cout <<loc<<endl;
                   return loc;
                   }

             void operator delete(void* ptr){
                  cout <<"Inside delete"<<endl;
                  free(ptr);
                  }
};


int main()
{
    int intArr[2];
    sample* samplePtr = new(intArr) sample(5);
    cout <<samplePtr<<endl;

    delete samplePtr;  
//    samplePtr->sample::~sample();
    getch();
}

输出:

Inside New
0x22ff38
Constructing Object
0x22ff38
Destructing Object
Inside Delete

在这里,我动态请求已在堆栈上分配的内存。我读到我需要在完成后显式调用析构函数。但是,当我尝试为堆栈上分配的内存调用 delete 时,我会调用析构函数。这是否意味着调用析构函数后释放堆栈上的内存?

如果我动态请求之前在堆上分配的内存,在这种情况下我需要调用 delete,但 delete 是否真的释放了堆栈上的内存?

【问题讨论】:

    标签: c++ memory-management placement-new


    【解决方案1】:

    普通的 new 操作符做了两件事:

    1. 调用动态内存管理器获取内存块
    2. 调用构造函数

    正常的删除操作符是相反的

    1. 调用析构函数
    2. 调用动态内存管理器释放内存块

    Placement new 只做一步:

    1. 调用构造函数

    所以“放置删除”应该只做一步:

    1. 调用析构函数

    您不应该像您所做的那样在放置 new 之后调用正常删除。 (原因是这样做会要求动态内存管理器删除它没有分配的块,从而导致未定义的行为)

    这一行是错误的:

    delete samplePtr;  // WRONG
    

    您需要执行“放置删除”,这只是对析构函数的原始调用:

    samplePtr->~sample(); // CORRECT
    

    【讨论】:

    • 谢谢,我现在明白了。我只需要调用析构函数。一旦对象自动超出范围,堆栈上的相应内存将被释放。
    【解决方案2】:

    你正在做的事情(free 的空闲内存不是由malloc 分配的)会导致未定义的行为 - 任何事情都可能发生。与delete 相同的指针不是通过new 获得的。与deletemalloc获得的指针相同或相反。

    仅仅因为它看起来“有效”并不意味着它是正确的。你不能free堆栈内存。在这种情况下您需要直接调用析构函数是正确的。

    【讨论】:

      【解决方案3】:

      这就是为什么放置 new 可能不好(实际上你应该尽可能避免它,在这种情况下,只需堆栈分配 object),你不应该delete 内存(因为它从来不是由new 创建的,而是你需要做samplePtr-&gt;~sample();

      【讨论】:

        猜你喜欢
        • 2011-12-09
        • 1970-01-01
        • 2011-05-13
        • 1970-01-01
        • 2010-09-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多