C++对象用new创建,用free()销毁;这有多糟糕?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4061514/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 14:25:52  来源:igfitidea点击:

C++ object created with new, destroyed with free(); How bad is this?

c++memory-management

提问by Dmitri

I am working on modifying a relatively large C++ program, where unfortunately it is not always clear whether someone before me used C or C++ syntax (this is in the electrical engineering department at a university, and we EEs are always tempted to use C for everything, and unfortunately in this case, people can actually get away with it).

我正在修改一个相对较大的 C++ 程序,不幸的是,在我之前是否有人使用 C 或 C++ 语法并不总是很清楚(这是在一所大学的电气工程系,我们 EE 总是很想使用 C 来做所有事情,不幸的是,在这种情况下,人们实际上可以侥幸逃脱)。

However, if someone creates an object:

但是,如果有人创建了一个对象:

Packet* thePacket = new Packet();

Packet* thePacket = new Packet();

Does it matter whether it is destroyed with delete thePacket;or free(thePacket);?

delete thePacket;或销毁它有关系free(thePacket);吗?

I realize that delete calls the destructor while free() does not, but Packet does not have a destructor. I am having a terrible time stuck in a memory management swamp here and I'm thinking this may be one of the many problems.

我意识到 delete 调用析构函数而 free() 没有,但 Packet 没有析构函数。我在这里陷入内存管理沼泽中度过了一段糟糕的时光,我认为这可能是众多问题之一。

回答by srean

Yes it does matter.

是的,这很重要。

For memory obtained using newyou mustuse delete.

对于使用获得的内存,new必须使用delete.

For memory obtained using mallocyou mustuse free.

对于使用获得的内存,malloc必须使用free.

newand mallocmay use different data structures internally to keep track of what and where it has allocated memory. So in order to free memory, you have to call that corresponding function that knows about those data structures. It is however generally a bad idea to mix these two types of memory allocation in a piece of code.

new并且malloc可以在内部使用不同的数据结构来跟踪它分配了内存的内容和位置。因此,为了释放内存,您必须调用知道这些数据结构的相应函数。然而,在一段代码中混合这两种类型的内存分配通常是一个坏主意。

回答by Ken Bloom

If you call free(), the destructor doesn't get called.

如果您调用free(),则不会调用析构函数。

Also, there's no guarantee that newand freeoperate on the same heap.

此外,不能保证newfree在同一个堆上运行。

You can also override newand deleteto operate specially on a particular class. If you do so, but call free()instead of the custom delete, then you miss whatever special behavior you had written into delete. (But you probably wouldn't be asking this question if you had done that, because you'd know what behaviors you were missing..)

您还可以覆盖newdelete专门对特定类进行操作。如果您这样做,但调用free()而不是 custom delete,那么您将错过您写入的任何特殊行为delete。(但如果你这样做了,你可能不会问这个问题,因为你会知道你错过了什么行为......)

回答by Omnifarious

Packethas a destructor, even if you haven't explicitly declared one. It has a default destructor. The default destructor probably doesn't actually do much, but you can't count on that being the case. It's up to the compiler what it does.

Packet有一个析构函数,即使你没有明确声明。它有一个默认的析构函数。默认析构函数实际上可能不会做太多事情,但您不能指望情况就是这样。这取决于编译器做什么。

newand mallocalso may have wildly different implementations. For example, delete is always called in a context where it has perfect information about the size of the data structure it's deleting at compile time. freedoes not have this luxury. It's possible that the allocator that newis using may not store the bytes at the beginning of the memory area stating how many bytes it occupies. This would lead freeto do entirely the wrong thing and crash your program when freeing something allocated with new.

new并且malloc也可能有截然不同的实现。例如,delete 总是在一个上下文中调用,在该上下文中它具有关于它在编译时删除的数据结构的大小的完美信息。 free没有这种奢侈。new正在使用的分配器可能不会将字节存储在内存区域的开头,说明它占用了多少字节。这将导致free完全错误的事情,并在释放分配给new.

Personally, if getting people to do the right thing or fixing the code yourself is completely impossible, I would declare my own global operator newthat called mallocso then freewould definitely not crash, even though it would still not call the destructor and be generally really ugly.

就个人而言,如果让人们做正确的事情或自己修复代码是完全不可能的,我会声明我自己的全局operator new调用mallocsofree绝对不会崩溃,即使它仍然不会调用析构函数并且通常非常丑陋。

回答by Chubsdad

In short, it is as bad as undefined behavior.

简而言之,它与未定义的行为一样糟糕。

This is quiet self explanatory.

这是安静的自我解释。

C Standard ($7.20.3.2/2) - "The free function causes the space pointed to by ptr to be deallocated, that is, made available for further allocation. If ptr is a null pointer, no action occurs. Otherwise, if the argument does not match a pointer earlier returned by the calloc, malloc, or realloc function, or if the space has been deallocated by a call to free or realloc, the behavior is undefined."

C 标准 ($7.20.3.2/2) - "free 函数导致 ptr 指向的空间被释放,即,可用于进一步分配。如果 ptr 是空指针,则不会发生任何操作。否则,如果参数与之前由 calloc、malloc 或 realloc 函数返回的指针不匹配,或者如果空间已通过调用 free 或 realloc 释放,则行为未定义。”

回答by slezica

You are absolutely right, it is NOTcorrect. As you said yourself, free won't call the destructor. Even if Packet doesn't have an explicit destructor, it's using an inherited one.

你是绝对正确的,这是正确的。正如您自己所说, free 不会调用析构函数。即使 Packet 没有显式析构函数,它也会使用继承的析构函数。

Using freeon an object created with newis like destroying only what a shallow-copy would reach. Deep-destroying NEEDS the destructor function.

使用free与创建的对象上new是只喜欢摧毁什么是浅拷贝将达到。深度销毁需要析构函数。

Also, I'm not sure objects created with new() are on the same memory map as malloc()'d memory. They are not guaranteed to be, I think.

另外,我不确定用 new() 创建的对象与 malloc() 的内存在同一个内存映射上。他们不能保证是,我想。

回答by Prasoon Saurav

if someone creates an object:

Packet* thePacket = new Packet();

Does it matter whether is is destroyed with delete thePacket; or free(thePacket); ?

如果有人创建了一个对象:

Packet* thePacket = new Packet();

是否与delete thePacket销毁有关系;或免费(数据包);?

Yes it does matter. free (thePacket)would invoke Undefined Behaviour but delete thePacketwould not and we all know Undefined Behaviour may have disastrous consequences.

是的,这很重要。free (thePacket)会调用未定义的行为,但delete thePacket不会,我们都知道未定义的行为可能会产生灾难性的后果。