智能指针——程序终止时的分段错误

Smart Pointers - Segmentation Fault at Program Termination

本文关键字:分段 错误 终止 指针 程序 智能      更新时间:2023-10-16

我一直在做一个状态的东西来取代一些我一直在使用的糟糕得多的代码。我希望尽可能地现代化,所以我在适当的地方使用STL。我决定用unique_ptrshared_ptr,这是我以前从未做过的。结果,我遇到了一个非常可怕的运行时错误:munmap_chunk(): invalid pointer: 0x00007fff7b3f08e0我所知道的是错误与free()malloc()有关,但我没有在我的代码中使用任何这些,所以我认为它来自STL内部。更奇怪的是,如果我在main开头放一个std::cout << "Hello World!n";,我只得到一个Segmentation fault。我的代码到目前为止相对较小:

state.hpp:

#pragma once
#include "state_manager.hpp"
class state{
 using manager_ptr = std::shared_ptr<state_manager>;
protected:
 manager_ptr man;
public:
 const manager_ptr manager() const;
 void manager(manager_ptr&& parent_manager);
};

state.cpp:

#include "state.hpp"
const state::manager_ptr state::manager() const{
 return man;
}
void state::manager(manager_ptr&& parent_manager){
 man = parent_manager;
}

state_manager.hpp:

#pragma once
#include <stack>
#include <memory>
class state;
class state_manager{
 using element = std::unique_ptr<state>;
 using container =  std::stack<element>;
protected:
 container states;
public:
 void push(element&& to_push);
 void pop();
 void change(element&& change_to);
};

state_manager.cpp:

#include "state_manager.hpp"
#include "state.hpp"
void state_manager::push(element&& to_push){
 states.push(std::forward<element>(to_push));
 states.top()->manager(std::shared_ptr<state_manager>(this));
}
void state_manager::pop(){
 states.pop();
}
void state_manager::change(element&& change_to){
 states.pop();
 push(std::forward<element>(change_to));
}

main.cpp:

#include "state_manager.hpp"
#include "state.hpp"
#include <iostream>
int main(int argc, const char* argv[]){
 state_manager test;
 test.push(std::make_unique<state>());
 test.change(std::make_unique<state>());
 test.pop();
}

这行代码中:

states.top()->manager(std::shared_ptr<state_manager>(this));

你正在构造一个指向thisshared_ptr。这意味着当shared_ptr的引用计数降为0时,它将delete this。这很糟糕,因为该类不是this的所有者。在您的示例中,this指针甚至没有由new分配,因此shared_ptr将无法删除它。

你可以在state_manager类中使用man的普通c++指针,因为它目前不需要指针的所有权。

或者你需要一些其他的方式来获得shared_ptrweak_ptr,指向this,例如通过传递它到push(这将是奇怪的)。