2013-05-09 61 views
2

这不是问题,只是我想回答的一个问题。内存释放冻结了我的程序

我正在制作具有粒子的2D应用程序。在单击处理我已经写了这个代码:

Particle *tempp = new Particle(); 
tempp->setPosition(mx, my); 
particles.push_back(tempp); // typeof particles = std::list<Particle*> 
delete tempp; // <- this line is the problem 

当我点击,一个粒子将在鼠标的位置创建。大约一秒后,它应该消失,这工作正常。消失后,我可以再次点击创建一个新的粒子。

但是,当我点击屏幕上仍然有一个粒子时,我的程序冻结并停止工作。

析构函数Particle和它的母公司析构函数都是空的。

没有调用delete我的程序运行良好,即使有多个粒子一次,甚至每帧多个。我只是想知道是什么导致这个冻结的问题。

+0

您正在添加一个指向temppp的指针 - 在tempp被删除后它指向什么? – Mark 2013-05-09 15:03:04

+1

为什么你将Tempp推入列表中,然后将它删除后?你的列表包含垃圾指针,任何尝试访问它们都可能导致你的程序崩溃。 – 2013-05-09 15:04:14

+0

那么在方法结束后,tempp指针仍然存在?如果我删除它,内存将被覆盖? – Broxzier 2013-05-09 15:23:24

回答

4

根据发布的代码,particles容器将包含悬挂指针。任何解除引用的尝试都是未定义的行为。我假设他们后来被使用,否则他们的存​​储似乎毫无意义。

调用push_back()不会复制指向对象,而是复制指针的值(动态分配的对象的内存地址)。如果Particle是便宜的复制,是可复制和多态的行为是不需要的只是将Particle存储在容器中。否则,建议使用智能指针(如std::unique_ptr)在从容器中移除时自动销毁Particle

+0

为什么创建第二个点(第一个点仍然存在)会导致问题?点击处理程序将在每次调用时调用,看起来'tempp'是函数的局部,并且会发生'new'内存分配。 (我赞同悬挂指针) – 2013-05-09 15:12:57

+0

@SuvP,第一个不存在,因为它已经立即删除。如果创建第二个“PArticle”访问“粒子”中的悬挂指针之一,那么它就是未定义的行为,并且是行为的可能原因。 – hmjd 2013-05-09 15:15:02

+0

查看当前的代码并假定其他地方没有其他事情发生,该列表在其他地方未被使用。 (OP只是添加地址和删除内存//不切实际我知道)那么它不应该是一个问题? (除了悬挂指针外)。所以也许OP在其他地方访问'list',这可能会导致这个问题? [只是想正确清除我的疑问] – 2013-05-09 15:19:54

3

当您将指针推入列表中时,您只需按下实际指针的副本,但不要复制它指向的内容。这意味着push_back之后你有两个指针指向相同内存。

如果你然后释放该内存,那么你有一个指向空闲内存的指针,该指针现在是无效的。

2

您正在将pointer放入容器中,然后删除它是一个问题。 push_back将复制pointer的值而不是pointer的内容,因此当您拨打delete时,容器中的pointer不再有效。所以现在你有一个悬挂的指针,当你解除引用时,这将是未定义的行为,但很可能是崩溃。

2

我相信这个解决方案在于你的第三行代码。请注意,粒子是指向粒子的指针的向量?那么,在第三行中,您将创建指针的副本并将其插入到列表中。在下一行中,您将释放该指针指向的内存。 该列表不存储您的粒子 - 它仅存储粒子的内存地址因此,当您删除粒子时,您告诉编译器重新使用包含有效数据的内存。

所以,在评论第4行时,问题就消失了,它并没有真的在那里崩溃 - 没有理由这样做。在有可能的情况是,它试图做与曾经是你记忆东西时崩溃,但在第3行

你可以榜上无名店实际颗粒作为修复被释放。

3

当我看到new,然后几行后delete,我宁愿看到使用的堆栈。除非Particle是巨大的(我怀疑),你可以更改您的代码如下:

Particle tempp; 
tempp.setPosition(mx, my); 
particles.push_back(tempp); // change particles to std::list<Particle> 

普雷斯托。你写的代码少,你不会炸毁。

+0

感谢您的回答。当然,这是有效的,但我想知道在这种情况下导致问题的原因是什么,而不是解决方案。如果不调用delete或使用改变vector来存储实际的粒子,它已经可以正常工作了。 – Broxzier 2013-05-09 15:35:18

+1

@Broxzier它没有正常工作,它只是没有炸毁。无论你是新手,你都必须删除。你的代码有新的和没有删除的内存泄漏。这几天我们有很多,所以它不会伤害你,但它不能正常工作。在这种情况下没有理由使用堆,并且尽可能使用良好的习惯。堆栈语义应该始终是您在C++中的首选 – 2013-05-09 15:55:07