簡體   English   中英

解除引用指針向量的迭代器時的Segfault

[英]Segfault when dereferencing iterator for vector of pointers

我有一個對象指針向量

    std::vector<Element*> elements;

在迭代向量時,我想重新引用迭代器以調用對象的方法。

    std::cout << (*it)->getName() << std::endl;

這導致了段錯誤。 相關代碼如下。

我認為問題在於我如何初始化向量,因為我可以將for循環移動到方法initialize()並且它工作正常。 takeTurn() ,向量具有適當的大小,指針包含正確的地址。 這是否意味着被指向的對象過早被破壞?

main.cpp中:

#include <vector>
#include <iostream>
#include "Element.h"

    std::vector<Element*> elements;

void initialize() {
    Element ice = Element("ice",1);
    Element fire = Element("fire",2);
    elements.push_back(&ice); 
    elements.push_back(&fire);
}

void takeTurn() {
    std::vector<Element*>::iterator it;
    for(it = elements.begin(); it != elements.end(); ++it) {
        std::cout << (*it)->getName() << std::endl;
    }
}

int main() {
    initialize();
    takeTurn();
    return 0;
}

element.h展開:

#include <string>

class Element {
    public:
        Element(std::string name, int id);
        int getID() { return id_; }
        std::string getName() { return name_; }

    private:
        int id_;
        std::string name_;
};

Element.cpp:

#include "Element.h"

Element::Element(std::string name, int id) {
    name_ = name;
    id_ = id;
}

您將指向局部變量的指針傳遞給向量:

Element ice = Element("ice",1);
Element fire = Element("fire",2);
elements.push_back(&ice); 
elements.push_back(&fire);

當你退出這個函數時, icefire不再存在,所以你留下了懸空指針。

這個問題的解決方案取決於你是否真的需要一個指針向量。 使用std::vector<Element>可能更簡單:

std::vector<Element> elements;

然后

elements.push_back(Element("ice",1));
elements.push_back(Element("fire",2));

您的初始化功能已損壞。 您創建本地對象,然后將其地址推送到向量。 但是當函數返回時,這些對象被銷毀,指針不再有效。 除非您需要多態性,否則最簡單的修復方法是僅生成Element對象的向量,而不是指針。

std::vector<Element> elements;
...
elements.push_back(Element("ice",1));
elements.push_back(Element("fire",2));

如果您需要多態,那么使用智能指針。

std::vector<std::unique_ptr<Element>> elements;
...
elements.push_back(std::unique_ptr<Element>(new Element("ice",1)));
elements.push_back(std::unique_ptr<Element>(new Element("fire",2)));

如果你繼續使用原始指針,那么你需要一些方法來確保對象的持久性,可能是通過用new分配它們。 然后,您需要確保在使用它們的每個指針上調用delete 我不推薦這條路線。

你將懸空指針推入你的矢量:

void initialize() {
    Element ice = Element("ice",1);
    Element fire = Element("fire",2);
    elements.push_back(&ice); 
    elements.push_back(&fire);
}

冰與火是局部變量。 你將地址推送到向量,然后當達到最終}時,兩者都被破壞。 稍后重新引用時,此無效指針行為未定義。

您的向量存儲指向堆棧上創建的局部變量的指針。 函數完成后,將回收這些變量占用的內存。 如果您嘗試訪問內存,則會出現段錯誤。

void initialize() {
    Element ice = Element("ice",1); // Local variable.
    Element fire = Element("fire",2); // Local variable.
    elements.push_back(&ice); 
    elements.push_back(&fire);
} // Ice and fire disappear.

為堆上的元素分配內存:

void initialize() {
    Element *ice = new Element("ice",1);
    Element *fire = new Element("fire",2); 
    elements.push_back(ice); 
    elements.push_back(fire);
} 

記得在完成后釋放內存!

typedef std::vector<Element *>::iterator EIter;
for (EIter it = elements.begin(); it != elements.end(); ++it) {
    delete *it;
}

暫無
暫無

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

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