2017-01-10 87 views
-4

我只是想出于好奇。我有一个构造函数和一个拷贝构造函数的结构,并尝试使用main中的拷贝构造函数初始化结构体,同时在主体中实现对指向结构体的指针的内存分配。复制构造初始化工作正常,但是当我尝试在主返回之前释放它时,它会在堆中导致断言错误。结构上的内存分配和复制构造函数

#include <stdio.h> 
    #include <malloc.h> 

    typedef struct tagInfo 
    { 
     int iX; 
     int iY; 

     tagInfo() {}; 

     tagInfo(int x, int y) 
      : iX(x), iY(y) {}; 

     ~tagInfo() {}; 

    }INFO; 

    int main (void) 
    { 
     INFO* pInfo = (INFO*)malloc(sizeof(INFO)); 

     pInfo = &INFO(10, 10); 

     free(pInfo); 

     return 0; 
    } 

如何安全地释放上述指针而不引起断言错误?

+4

不要垃圾邮件的标签!这不是有效的C代码! – StoryTeller

+0

看到它是C++,你应该使用'new' /'delete'。除此之外 - 存储一个临时的内存地址,然后使用它(在'free'中)是UB(永远不会释放malloc'ed空间来创建内存泄漏)。 –

+2

通过将C习语混合到C++代码中,而没有清楚地理解其意义,您正在弄得一团糟。很好地学习C++的方法不是通过试验和错误,而是从底层开始,接近它,而没有以前学过的语言的偏见。 [选一本好书](http://stackoverflow.com/questions/388242/the-definitive-c-book-guide-and-list)适合初学者,并一步一步接受。 – StoryTeller

回答

0

我认为基本的误解是一个拷贝构造并不一个对象的内容复制到相同类型的(已经存在的)其他对象,而是生成一个新的对象,该对象被初始化基于要复制的对象的内容。

在您的代码中,您使用mallocINFO类型的对象预留内存,并让pInfo指向该内存。

接下来,pInfo = &INFO(10, 10)您在堆栈上(而不是在堆上)实例化一个INFO类型的新对象,并让pInfo指向此对象(位于堆栈上!)的内存地址。顺便说一句,你没有提及你的malloc -ed内存,因为指针pInfo不再指向malloc -ed地址,而是指向新对象。

free(pInfo)是至关重要的,因为你释放一个内存地址,它之前没有被分配到malloc

其实,你应该做到以下几点:

INFO* pInfo = new INFO(10, 10); 
... 
delete pInfo; 
+0

谢谢!这是我正在寻找的答案类型!我知道我应该在C++代码中使用新的删除,但我只是想用malloc和free来试用它,并进行比较。感谢您的酷! –

2

mallocfree不应该在C++中使用,因为它们不处理对象的构造/销毁。


在现代的C,如果你要建模特有的股权,或std::shared_ptr如果要模拟共享所有权 ++,你应该使用std::unique_ptr - 这些被称为“智能指针”并提供一个安全的方式管理动态内存,自动处理释放/销毁。例如:

int main (void) 
{ 
    auto pInfo = std::make_unique<INFO>(10, 10); 

    return 0; 
} 

如果你真的想下去手动内存管理的道路,就必须使用new(用于分配+建设)delete(为释放+毁灭)。例如:

int main (void) 
{ 
    INFO* pInfo = new INFO(10, 10); 
    delete pInfo; 

    return 0; 
} 
0

在一般情况下,你可以做到这一点与放置新的,但它是非常气馁:

// allocate 
void* pInfoMem = malloc(sizeof(INFO)); 
// construct 
INFO* pInfo = new(pInfoMem) INFO(10, 10); 

// destruct 
pInfo->INFO::~INFO(); 
// free 
free(pInfoMem); 

但随后你需要在释放之前手动调用析构函数。

这是很容易只是做(其它答案提):

INFO* pInfo = new INFO(10, 10); 
delete pInfo;