簡體   English   中英

使用shared_ptr的引用時的SIGSEGV

[英]SIGSEGV when using references of shared_ptr

如果運行以下C ++代碼,您將獲得SIGSEGV:

#include <iostream>
#include <vector>
#include <memory>

class Node {
public:
    std::vector<std::shared_ptr<Node>> childNodes;
};

void addChild(const std::shared_ptr<Node> &node, std::shared_ptr<Node> &parentNode) {
    std::shared_ptr<Node> newNode = std::make_shared<Node>();
    std::cout << node->childNodes.size() << std::endl;
    parentNode->childNodes.push_back(newNode);
    std::cout << node->childNodes.size() << std::endl; // the program crashes when running this line
}

int main(int argc, char *argv[]) {
    std::shared_ptr<Node> parentNode = std::make_shared<Node>();
    parentNode->childNodes.emplace_back(std::make_shared<Node>());
    std::shared_ptr<Node>& childNode = parentNode->childNodes[0];
    addChild(childNode, parentNode);
    return 0;
}

我不知道為什么會崩潰。 但是我發現,如果我在主要功能中更改了這一行:

std::shared_ptr<Node>& childNode = parentNode->childNodes[0];

std::shared_ptr<Node> childNode = parentNode->childNodes[0];

問題將消失。 程序正確輸出兩個零並安全退出,為什么? 是什么原因導致最初的崩潰,以及為什么修改可以解決該問題?

向量中的push_back會使向量的所有迭代器,指針和引用無效。

由於node是對parentNode->childNodes元素的引用,因此將其推入該元素會使該引用無效。 因此,僅訪問node->childNodes.size()是未定義的行為。

當您在向量中使用元素的副本時, node引用仍然有效,因為它所引用的shared_ptr仍然存在於向量管理的存儲器之外。

您還可以通過簡單地將引用傳遞給節點本身來避免復制shared_ptr

void addChild(const Node &node, std::shared_ptr<Node> &parentNode)

即使重新分配了任何shared_ptr,對Node的引用也不會無效。

當您在addChild中將newNodenewNode此處時:

parentNode->childNodes.push_back(newNode);

你可能會失效,你承擔了參考mainparentNode->childNodes[0]而這又被稱為nodeaddChild

最后,當您取消引用有問題的行中的node時,這將導致無效的讀取:

node->childNodes

依次觸發段錯誤。


相反,如果您創建了parentNode->childNodes[0]的副本,那么一切都很好,因為在這種情況下,您沒有對childNodes std::vector任何元素的任何引用,因此任何元素都不會失效。

請注意, 指針本身( std::vector包含的指針 )總是很好的,因為它們在任何一個版本中都不會被修改(並且在工作情況下創建std::shared_ptr的副本時,一切都會正常進行)以及由於std::shared_ptr提供的引用計數機制而導致的破壞)。

暫無
暫無

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

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