I've been making a state-thingy to replace some much poorer code I've been using. I wanted to be as modern as possible, so I'm using STL wherever appropriate. I decided to use unique_ptr
and shared_ptr
, which I've never done before. As a result, I've hit a very scary run-time error: munmap_chunk(): invalid pointer: 0x00007fff7b3f08e0
All I know is the error has to do with free()
and malloc()
, but I haven't used any of that in my code, so I assume it's coming from inside STL. To make things even stranger, if I put a std::cout << "Hello World!\n";
at the beginning of main, I just get a Segmentation fault
My code is relatively small so-far:
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();
}
In this line of code:
states.top()->manager(std::shared_ptr<state_manager>(this));
You are constructing a shared_ptr
that points to this
. That means that when the shared_ptr's reference count drops to zero, it will delete
this
. This is bad, as the class is not the owner of this
. In your case, the this
pointer isn't even allocated by new
, so the shared_ptr will not be able to delete it.
You could use just a normal C++ pointer for man
in your state_manager
class, as it currently doesn't need ownership of the pointer.
Alternatively you need some other way to get a shared_ptr
or weak_ptr
that points to this
, e.g. by passing it in to push
(which would be weird).