我被指派在MFC中处理一些遗留的C ++代码。我在这个地方找到的一件事是分配如下:
struct Point
{
float x,y,z;
};
...
void someFunc( void )
{
int numPoints = ...;
Point* pArray = (Point*)new BYTE[ numPoints * sizeof(Point) ];
...
//do some stuff with points
...
delete [] pArray;
}
我意识到这个代码在很多层面都是错误的(C风格的演员,使用像new
这样的malloc
,令人困惑等等。我也意识到,如果 Point 定义了一个构造函数,那么如果定义了析构函数,它就不会被调用,而delete []
会发生奇怪的事情。
问题: 我正在修理这些事件,无论它们出现在哪里都是理所当然的。然而,我以前从未见过这样的事情,它有让我疑惑此代码是否有可能导致内存泄漏/损坏,因为它当前(没有构造函数/析构函数,但指针类型不匹配),或者只要数组只包含结构/基元类型,它是否安全?
答案 0 :(得分:6)
由于new[]
/ delete[]
中的指针类型不匹配,因此代码正式导致未定义的行为。在实践中它应该工作正常。
通过向delete-expression
添加强制转换,可以轻松修复指针类型不匹配问题delete [] (BYTE *) pArray;
如果Point
类型定义为问题中所示(即使用简单的构造函数和析构函数),则此更正解决了此代码中存在的所有正式问题。从语言的角度来看,具有普通构造函数(析构函数)的对象的生命周期与其存储持续时间同时开始(结束)。即没有要求执行构造函数(析构函数)的实际调用。
答案 1 :(得分:1)
只要构造函数和析构函数不执行任何操作,那么您就是安全的。
答案 2 :(得分:0)
只要您确保它确实为每个delete[]
调用匹配的new[]
,它就不会泄漏 - 但是如果任何被评论的代码都可能抛出异常out,这将很难保证(基本上,你需要捕获任何可能的异常,删除内存,然后重新抛出异常)。
答案 3 :(得分:0)
我首先要弄清楚为什么代码首先以这种方式编写。这可能只是因为程序员不知道更好,或者因为他们试图在编译器中解决一些时髦的缺陷。但可能有一个你不知道的真正原因。如果有,那么除非您理解该原因及其副作用,否则您可能会通过更改此代码来引入缺陷。
这样做,并且假设代码现在没有特殊原因需要这样,你应该安全地更改代码以使用更现代和正确的结构。
但为什么呢?我理解使代码更正确的动机。但是你真正获得了什么呢?如果代码以现在的方式运行(一个很大的假设),那么通过更改代码,您可能会获得使代码更易于理解的好处,但是您更改的每一行代码都会引发新错误的可能性。写的。
如果最后你决定继续改变,为什么要中途停止?考虑完全删除所有new
和delete
,并将其替换为vector
等。