我在释放 _wcsdup 分配的内存以创建 TComboBox 的 TObject 指针时遇到问题。我认为当 TComboBox 或 Parent TForm 被释放时,该内存会自动释放。我正在使用 TComboBox 函数 AddItem() 将可见文本和指针值添加到 TComboBox。当我退出应用程序时,我的内存泄漏检测器显示 _wcsdup 分配的内存尚未释放。
我的代码如下。
int i=0;
UnicodeString Description;
UnicodeString Symbol;
wchar_t *MyPointerValue;
for(i=0; i<MyStringList1->Count; i++){
Description = MyStringList1->Strings[i];
Symbol = MyStringList2->Strings[i];
MyPointerValue = _wcsdup(Symbol.c_str());
ComboBox1->AddItem(Description, (TObject *) MyPointerValue );
}
我尝试添加代码 if(MyPointerValue != NULL){ free(MyPointerValue);在我的 for 循环中,如下所示,但这会释放指针内存,因此不会向 TComboBox 添加任何内容。这确实解决了我的内存泄漏软件找到不可用内存的问题。
for(i=0; i<MyStringList1->Count; i++){
Description = MyStringList1->Strings[i];
Symbol = MyStringList2->Strings[i];
MyPointerValue = _wcsdup(Symbol.c_str());
ComboBox1->AddItem(Description, (TObject *) MyPointerValue );
if(MyPointerValue != NULL){
free(MyPointerValue);
}
}
我还尝试通过将以下代码添加到 FormClose 事件来直接释放 ComboBox TObject 指针内存。 调用 ->Free();产生错误。
for(i=ComboBox1->Items->Count-1; i>-1; i--){
if( ComboBox1->Items->Objects[i] ){
ComboBox1->Items->Objects[i]->Free();
}
}
如何确保 _wcsdup 内存始终被释放?
请注意,我正在使用 C++Builder 12.2 Update 2 和 Win64X VCL 平台。
我无法释放
分配的内存来为_wcsdup
创建TObject
指针。TComboBox
我不建议使用
_wcsdup()
来完成此任务。 使用 new
来创建和存储 UnicodeString
对象,例如:
for(int i = 0; i < MyStringList1->Count; ++i)
{
UnicodeString Description = MyStringList1->Strings[i];
UnicodeString Symbol = MyStringList2->Strings[i];
UnicodeString *MyPointerValue = new UnicodeString(Symbol);
ComboBox1->AddItem(Description, (TObject *) MyPointerValue );
}
我认为当
或父级TComboBox
被释放时,该内存会自动释放。TForm
不,内存没有被释放。使用
_wcsdup()
手动分配的内存必须使用 free()
(或 delete
与 new
)手动释放。
即使您将实际的基于
TObject
的对象存储到 TComboBox::Items->Objects[]
属性中,VCL 仍然不会自动释放内存。 TComboBox
根本不拥有TObject
指针,它们是您拥有的任意数据,VCL对它们指向的内容不做任何假设。
将此与
TStringList::Objects[]
属性进行对比,通过将 TStringList::OwnsObjects
属性设置为 true
,可以自动获取所有权并释放。 但是,这仅适用于基于
TObject
的有效对象。
我正在使用TComboBox
函数AddItem()
将可见文本和指针值添加到TComboBox
。当我退出应用程序时,我的内存泄漏检测器显示_wcsdup
分配的内存尚未释放。
这是正确的,因为您没有释放手动分配的内存。
我尝试在如下所示的if(MyPointerValue != NULL){ free(MyPointerValue); }
循环中添加代码for
,但这会释放指针内存,因此不会向TComboBox
添加任何内容。这确实解决了我的内存泄漏软件找到不可用内存的问题。
这正是您需要做的。 然而,你在“错误”的地方做这件事。 不要在填充 for
的
TComboBox
循环中执行 in 操作。 在使用完
TComboBox
项目后执行此操作,例如在程序关闭期间,或者使用新项目重新填充 TComboBox
时。
我还尝试通过将以下代码添加到 TObject
事件来直接释放 ComboBox
指针内存。对FormClose
的调用会生成错误。 这是正确的方法,但是您必须使用
->Free();
free()
而不是
TObject::Free()
,因为您没有存储基于 TObject
的有效对象,这就是 Free()
崩溃的原因。尝试更像这样的事情:
void __fastcall TMyForm::FormClose(TObjct* Sender, TCloseAction &Action)
{
ClearComboBox();
}
void __fastcall TMyForm::PopulateComboBox()
{
ClearComboBox();
for(int i = 0; i < MyStringList1->Count; ++i)
{
UnicodeString Description = MyStringList1->Strings[i];
UnicodeString Symbol = MyStringList2->Strings[i];
wchar_t *MyPointerValue = _wcsdup(Symbol.c_str());
// or:
UnicodeString *MyPointerValue = new UnicodeString(Symbol);
ComboBox1->AddItem(Description, (TObject *) MyPointerValue );
}
}
void __fastcall TMyForm::ClearComboBox()
{
for(int i = ComboBox1->Items->Count-1; i > -1; --i)
{
free( (wchar_t*) ComboBox1->Items->Objects[i]) );
// or:
delete (UnicodeString*) ComboBox1->Items->Objects[i]);
}
ComboBox1->Clear();
}
MyStringList1
和
MyStringList2
列表在填充 TComboBox
时保持有效,那么更简单的解决方案是将 indexes存储在
Objects[]
属性中,而不是实际的 strings。 这样,您就不必担心释放
TComboBox
中的内存,例如:void __fastcall TMyForm::PopulateComboBox()
{
ComboBox1->Clear();
for(int i = 0; i < MyStringList1->Count; ++i)
{
UnicodeString Description = MyStringList1->Strings[i];
UnicodeString Symbol = MyStringList2->Strings[i];
ComboBox1->AddItem(Description, (TObject *) (IntPtr) i );
}
}
然后您可以在需要时检索
Symbol
字符串:
int index = (int) (IntPtr) ComboBox1->Items->Objects[...];
UnicodeString Symbol = MyStringList2->Strings[index];
...