Cod*_*345 3 c++ delphi memory-leaks c++builder virtualtreeview
我在C++ Builder中使用VirtualTreeView并使用它的结构如下:
struct TVTNodeData
   {
   int Index;
   UnicodeString Caption;
   }
我使用具有以下内容的循环预填充树的节点:
TVirtualNode *Node = VTree->AddChild(NULL);
pNode = (TVTNodeData *)VTree->GetNodeData(Node);
pNode->Index = 1;
pNode->Caption = "Whatever";
我注意到应用程序的内存不断增加(内存泄漏),即使我清除树并重新加载它.此页面 - http://www.remkoweijnen.nl/blog/2010/06/09/memory-leaks-when-using-virtual-treeview-component/建议在OnFreeNode事件中执行Finalize().目前很好.
但是C++中没有Finalize().我pNode->Caption=""在OnFreeNode事件中尝试过并且内存不再被大量分配,但它仍然有点.我认为即使它被清空也可能会引用UnicodeString(引用计数> 0).
如何OnFreeNode在C++中为UnicodeString 释放节点数据?我知道UnicodeString是在所有引用计数为零之前分配的 - 那么如何强制引用计数变为零?
另外,如果节点被分配了OnNodeInit- 在OnFreeNode事件中同样适用吗?
如果TVTNodeData结构纯粹是虚拟的 - 节点永远不可见也不会使用AddChild和OnNodeInit初始化,那么需要Finalize,结构是否甚至存在于内存中呢?
更新:我后来发现我正在错误地测量内存使用情况,而对于将字符串设置为空字符串的字符串来说,它确实足以清除内存数据.但是 - 正如Rob Kennedy在下面的回答中所建议的那样,调用struct~destructor甚至比Finalize更好,并且更容易,因为它清除了整个结构(如果你有更多的字符串).
Delphi Finalize具有释放记录中任何编译器管理类型的效果.在C++中,这通常是类型析构函数的工作.在OnFreeNode事件处理程序中,直接调用数据类型的析构函数:
TVTNodeData* const pNode = static_cast<TVTNodeData*>(Sender->GetNodeData(Node));
pNode->~TVTNodeData();
这将调用UnicodeString对象的析构函数,它将释放相关的字符数据.当树控件TVTNodeData为节点分配时,它与TVirtualNode对象本身位于同一块内存中,因此您不能只调用它delete.
树控件使用全零位初始化数据.如果数据中的对象不是正确的初始化(正式更正,包括所有非POD类型),那么您应该在事件中调用数据的构造函数OnInitNode.使用placement new来做到这一点.例如:
TVTNodeData* const pNode = static_cast<TVTNodeData*>(Sender->GetNodeData(Node));
new (pNode) TVTNodeData();
这将调用TVTNodeData成员的构造函数而不为其他TVTNodeData实例分配内存.
如果一个节点从未被初始化,那么它也不会被最终确定.该OnInitNode事件将永远不会运行,因此树将知道该节点尚未初始化.未初始化的节点无法完成,因此您无需担心.
| 归档时间: | 
 | 
| 查看次数: | 1069 次 | 
| 最近记录: |