2013-05-09 25 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