假设我有一个包含Records的类TwoWayList,而GetRec实际上在堆上创建了一个新列表,这里是方法
void GetRec(TwoWayList<Record> &rec)
{
TwoWayList<Record>* list= new TwoWayList<Record>();
Record r;
list->Insert(&r);
}
现在我有以下两个场景,第一个在我调用delete时死亡,另一个我只是得到一个空的引用记录,所以当我调用MoveToStart()时我得到一个段错误,但是如果我只是删除它有效...
int main () {
TwoWayList<Record> record;
GetRec(record);
record.MoveToStart();
delete &record;//crash
return 0;
}
int main () {
TwoWayList<Record> *record;
GetRec(*record);
record->MoveToStart(); //segfault
delete record;
return 0;
}
所以这里发生了什么?我在方法的堆中创建一个TwoWayList,因此我不能删除(事实上,如果我不删除它不会是泄漏吗?)是什么方法从这里的方法获取TwoWayList以便我以后可以删除吗?
谢谢
丹尼尔
答案 0 :(得分:5)
你的第一个main
在堆栈上创建记录 - 而不是堆。因此,您尝试delete
堆栈变量的地址崩溃。
您的第二个main
永远不会分配record
。因此,当您尝试使用指针时,会出现段错误。
此外,您的函数分配内存,但随后忘记它并泄漏它。我的意思是你创建一个新的list
,但永远不要抓住指针。一旦函数退出,你就不再有指向你创建的列表的指针 - 可能不是你想要做的。
GetRec
也会忽略输入参数 - 也可能不是你想要的。
猜猜你在尝试什么......
void GetRec(TwoWayList<Record> &rec)
{
Record r;
rec.Insert(r);
}
int main () {
TwoWayList<Record> record;
GetRec(record);
record.MoveToStart();
return 0;
}
这会创建一个TwoWayList(命名记录),将对记录的引用传递给函数GetRec。 GetRec创建一个Record并将其插入TwoWayList。回到main
,它在记录中调用MoveToStart(现在插入了一个Record)。
这可以通过使用堆栈避免任何新/删除问题,当您将其插入TwoWayList时,以成本复制记录。令人怀疑的是,该副本的性能成本对您来说很重要。但如果确实如此,那就说出来。
答案 1 :(得分:1)
void GetRec(TwoWayList<Record> &rec)
{
TwoWayList<Record> *list= new TwoWayList<Record>();
Record r;
list->Insert(&r);
}
好吧,你在堆上分配一些内存,让它的指针超出范围。你确定你不是故意这样做:
rec = new TwoWayList<Record>(); //rec should really be a reference to a pointer
TwoWayList<Record> record;
delete &record;//crash
您无法删除堆栈中的对象。
TwoWayList<Record> *record;
GetRec(*record);
record->MoveToStart(); //segfault
delete record;
这里你的GetRec没有改变记录,我认为你想要的。由于记录指向垃圾,对该对象的调用显然会中断。
答案 2 :(得分:0)
在第一个示例中,您要删除一个不好的局部变量。不需要;当函数超出函数末尾的范围时,变量被“删除”。
您的第二个示例是尝试使用未初始化的指针。您需要使用TwoWayList<Record>
分配new
的实例。
此外,您的GetRec
函数正在堆上分配一个列表,并且从不调用delete
,这会导致内存泄漏。