簡體   English   中英

刪除指針向量時,調試斷言失敗

[英]Debug assertion failed when deleting a vector of pointers

我有一個保存pointer類的pointervector

vector<Entity*> editorElements;
vector<Entity*> entities;
vector<DirectionalLight*> dirLights;
vector<PointLight*> pointLights;
vector<SpotLight*> spotLights;

這段代碼在我的Scene類中。 Scene的ctor和析構函數如下所示:

Scene()
{
    editorElements = vector<Entity*>();
    entities = vector<Entity*>();
    dirLights = vector<DirectionalLight*>();
    pointLights = vector<PointLight*>();
    spotLights = vector<SpotLight*>();
}

~Scene()
{
    delete[] &entities;  // ERROR HERE
    delete[] &dirLights;
    delete[] &pointLights;
    delete[] &spotLights;
    delete[] &editorElements;
}

在析構函數中,我在ERROR HERE標記了一行。 我先輸入哪個向量都沒有關系,但我總是會得到錯誤。 奇怪的是,直到最近(沒有碰到Scene類或使用Scene實例的任何其他類中的任何東西),它都運行良好,突然之間它引發了一個異常:

在此處輸入圖片說明

vector s為空或有元素都沒有關系,它給出的誤差都相同。

我需要協助以解決此問題。

向量不是更新的指針,更不用說更新的數組了。 因此,您不應該刪除它們。 如果需要對向量中存儲的指針調用delete,則應遍歷向量,刪除每個元素。 但是最好改為存儲智能指針(例如std::unique_ptr<Entity> 。也就是說,如果您需要存儲所有指向動態分配對象的指針。

請注意,如果最終刪除了析構函數中的元素,則還需要注意3/5的規則

刪除表達式 delete [] x的描述如下:

銷毀由new []表達式創建的數組

因此delete[] &entities &entities是由new[] -expression創建的數組時, delete[] &entities 才有意義。 對?

但是entitiesstd::vector<Entity*> ,而不是Entity[] 您不是使用new[]創建它的,因此不能使用delete[]刪除它。

std::vector不是數組的語法糖,它是模板類,而std::vector<Entity*> entities不是數組,它是具有構造函數和析構函數的對象。 這也告訴我們,這句話

entities = vector<Entity*>();

沒有任何用處- entities是一個對象,因此它已經是默認構造的。 您只是默認構造一個相同類型的匿名臨時文件,然后進行分配。

最后,在這里將原始指針存儲在向量中是可以的,因為向量不影響對象的生存期。 在大多數情況下,最好讓向量擁有對象,這樣您就不必擔心手動刪除它們,直接使用

vector<Entity>

或間接與

vector<unique_ptr<Entity>>

注意 一個好的原則是:你不應該使用newnew[] deletedelete[]在用戶代碼在所有

使用類對象來管理您的存儲,因為編譯器將為您調用其構造函數和析構函數。

如果需要自定義類,請編寫一個管理內存的類,以免與程序邏輯脫鈎。 否則,如果您確實需要該所有權模型,則只需使用標准庫工具,例如std::vectorstd::arraystd::unique_ptrstd::shared_ptr等等。

突然間它提出了一個例外

這是因為嘗試刪除不應該刪除的內容。 delete[]語法用於刪除動態分配的數組 但是您為它提供了一個指向std::vector實例的指針。 因此,編譯器將此地址當作刪除對象,就好像它是一個數組一樣,其中包括找出其大小,然后刪除整個段。 但是沒有合適的數字,因為它不是數組,所以在運行時,您最終試圖在沒有訪問權限的地方刪除某些內容,因此斷言失敗,因為這是訪問違反,也稱為段錯誤。

同樣, vector是管理自己的內存的類。 如果要釋放保存在此容器中的實體(即,動態分配的各個元素本身),則應遍歷它們並刪除每個元素。 例如,方便地使用auto和基於范圍的for循環,如下所示:

for (auto ptr : entities)
    delete ptr;

但是,在大多數情況下,您最好節省這些內存管理開銷,並選擇std::unique_ptr而不是原始指針:

#include <memory>
...
std::vector<std::unique_ptr<Entity>> entities;

這樣,您不必擔心釋放任何內存,因為一旦銷毀了std:: unique_ptr ,它就會被釋放,這是vector銷毀的一部分。

此外,這是不必要的,可能不是您打算執行的操作:

entities = vector<Entity*>();

因為vector對象本身已經在此行之前定義(因此存在),並且它所做的就是創建一個相同的新對象並將其分配給entities

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM