我继承了一些包含以下段落的代码:
TStringList* pPortList(NULL);
pPortList = FindCommPorts();
ConnectionDialog->PortList = pPortList;
int nModalReturn = ConnectionDialog->ShowModal();
delete pPortList;
FindCommPorts()
是一个创建new TStringList()
,填充并返回它的函数。
我很想用这个替换代码:
ConnectionDialog->PortList = FindCommPorts();
int nModalReturn = ConnectionDialog->ShowModal();
然后我意识到我对C ++的所有权语义不够熟悉,无法确定这一点。这会泄漏内存,因为FindCommPorts()
的结果永远不会delete
d?
编辑:再次查看代码,我认为原始版本没有导致悬挂指针 - 事实证明ConnectionDialog->PortList
实际上是一个属性(我'使用Borland C ++ Builder 6)。此属性有一个自定义setter,可以将字符串复制出TStringList
,之后不会使用传递的指针本身。我为之前没有提到这个问题而道歉 - 编写代码的方式,看起来确实很糟糕。
答案 0 :(得分:1)
如果它永远不是delete
d,那么是的,你会泄漏内存。但是,您对此代码的问题更严重。想想你的情况:
FindCommPorts()
返回指针ConnectionDialog->PortList
指向FindCommPorts()
结果指向的相同内存。delete
pPortList
指向的内存中的对象,与ConnectionDialog->PortList
指向的内存相同! 此后,PortList
变量指向已删除的内存,您不应该访问它。如果您需要再次使用此指针,则无论如何都不应删除它,因此您不必担心将FindCommPorts()
的结果直接分配给ConnectionDialog->PortList
。只需确保在完成后删除它。
如果您需要该指针永远有效,那么这种情况不是内存泄漏,因为需要数据。在这种情况下,程序终止时将释放内存。
修改强>
阅读完问题的编辑后,我发现你是对的。您确实需要临时变量以防止内存泄漏。如果不这样做,属性的setter将复制FindCommPorts()
返回的指针所指向的对象的副本,然后内存将保持分配状态,但没有包含指向它的指针的变量。在这种情况下,您可以创建临时变量,然后在执行赋值后将其删除。