after failing to find a normal solution with new and delete I found something called smart pointers
so i thought maybe those could help me fix this memory leak. i might have more than one
The code i started refactoring first is a bit complex( for me atleast)
Its a Messaging system to enable communication between different parts of code
it utilizes Polymorphism with a base msg class and will have multiple derivatives (such as PhysicsMSG or AnimationMSG)
it worked pretty great at first i thought. there is a MSGdispatcher class and a MSGreciever class.
Message receiver has a std::vector <msg*> and a getMSG(msg* message) function
the Message Dispatcher has a std::vector<MSGreciever*> sendMSG(msg* message) that calls getMSG and passes along message to objects who have a matching Identifier.
at first it seem like it was working perfectly. i made a pair of objects to communicate with each other. one that handled behaviour, and connected that to my sprite.
but when i made more than one pair of objects it stopped working right. all kinds of bad memory stuff started happening. heap corruption, de-reference null_ptrs and all kinds of stuff.
i started at first with just messages befor i change anything else. and now im telling it to use std::shared_ptr<msg> instead of msg.
after lots of researching and researching and eliminating error messages i have just 4 instances of 1 error in particular
Compiler Error C2259 : You cannot instantiate a class or structure with one or more pure virtual functions. To instantiate objects of a derived class, the derived class must override each pure virtual function.
but as far as i can tell i have overrode all virtual functions. so since this is my first time working with smart ptrs im not sure what i am doing wrong. I will link below the code i find relevant.
Message headers
Code: Select all
class msg{
public:
msg();
virtual~msg() = default;
msg(ID target, ID sender);
virtual void update(void * Variables)=0;
ID getTargetID();
ID getSenderID();
ID m_TargetID;
ID m_SenderID;
MSGTYPE m_type;
};
class PhysicsMSG : public msg {
public:
PhysicsMSG();
~PhysicsMSG() = default;
PhysicsMSG( Vec2DF velocity , float dt, ID target, ID Sender );
PhysicsMSG(PhysicsMSG& Copy);
void update (void* Variables)override;
Vec2DF m_VecPayload;
float m_DeltaTime;
};
class AnimationMSG : public msg{
public:
AnimationMSG();
~AnimationMSG() = default;
AnimationMSG(int curTile, int AnimateFrames, state desiredState , ID target, ID Sender );
AnimationMSG(AnimationMSG& Copy);
void update(void* Variables)override;
int m_curFrameSet;
int m_AnimationFramesSet;
state m_state;
};
class MSGreciever{
public:
MSGreciever();
MSGreciever(ID identity);
~MSGreciever();
bool handleMSG(void *passedvar);
void handleMSGS(void *passedvar);
void getMSGS(std::shared_ptr<msg> message );
MSGTYPE peakatMSGS(int indextoPeak);
void CheckForGarbage();
std::vector < std::shared_ptr<msg> > que;
ID SentTo;
};
class MSGdispatcher {
public:
MSGdispatcher();
MSGdispatcher( MSGreciever* FirstTarget );
~MSGdispatcher();
// void sendMSG(msg Message);
void registerMSGER (MSGreciever* listener );
void sendMSG(std::shared_ptr<msg> Message);
std::vector<MSGreciever*> m_Listeners;
};
};
Code: Select all
msg::msg()
{
}
msg::msg(ID target, ID sender)
{
m_TargetID = target;
m_SenderID = sender;
m_type = MSGTYPE::Failed;
}
ID msg::getTargetID(){return m_TargetID;}
ID msg::getSenderID()
{
return m_SenderID;
}
PhysicsMSG::PhysicsMSG(){
}
PhysicsMSG::PhysicsMSG(Vec2DF velocity, float dt, ID target, ID Sender ){
m_VecPayload = velocity;
m_type = MSGTYPE::Physics;
m_TargetID = target;
m_SenderID = Sender;
m_DeltaTime = dt;
}
PhysicsMSG::PhysicsMSG(PhysicsMSG & Copy)
{
this->m_VecPayload = Copy.m_VecPayload;
this->m_type = Copy.m_type;
this->m_TargetID = Copy.m_TargetID;
this->m_SenderID = Copy.m_SenderID;
this->m_DeltaTime = Copy.m_DeltaTime;
}
void PhysicsMSG::update( void* Variables ){
if((Variables) == nullptr){
std::cout << " Got Null" <<std::endl;
}else{
((Vec2DF* )Variables )->x = m_VecPayload.Approach(m_VecPayload.x,((Vec2DF*)Variables)->x, ( m_DeltaTime * 0.15f) );
((Vec2DF* )Variables )->y = m_VecPayload.Approach(m_VecPayload.y,((Vec2DF*)Variables)->y, ( m_DeltaTime ) * 0.15f);
((Vec2DF*)Variables)->operator+= (m_VecPayload *= 0.15f );
}
}
AnimationMSG::AnimationMSG()
{
}
AnimationMSG::AnimationMSG(int curTile, int AnimateFrames , state desiredState, ID target, ID Sender ){
m_type = MSGTYPE::Animation;
m_curFrameSet = curTile;
m_AnimationFramesSet = AnimateFrames;
m_TargetID = target;
m_SenderID = Sender;
m_state = desiredState;
}
AnimationMSG::AnimationMSG(AnimationMSG & Copy)
{
this->m_type = Copy.m_type;
this->m_curFrameSet = Copy.m_curFrameSet;
this->m_AnimationFramesSet = Copy.m_AnimationFramesSet;
this->m_TargetID = Copy.m_TargetID;
this->m_SenderID = Copy.m_SenderID;
this->m_state = Copy.m_state;
}
void AnimationMSG::update(void* Variables){
if((Variables) == nullptr){
std::cout << " Got Null" <<std::endl;
}else{
((TileMap*)Variables)->setCurTile(m_curFrameSet);
((TileMap*)Variables)->setNumAnimFrames(m_AnimationFramesSet);
((TileMap*)Variables)->setState(m_state);
}
}
MSGdispatcher::MSGdispatcher(){}
MSGdispatcher::MSGdispatcher( MSGreciever* FirstTarget ){
registerMSGER(FirstTarget);
}
MSGdispatcher::~MSGdispatcher(){}
MSGreciever::MSGreciever(){}
MSGreciever::MSGreciever(ID Owner ){
SentTo = Owner;
que.clear();
}
MSGreciever::~MSGreciever(){}
void MSGdispatcher::sendMSG(std::shared_ptr<msg> Message){
for (auto i = 0; i < m_Listeners.size() ; i++){
m_Listeners[i]->getMSGS(Message);
}
}
void MSGdispatcher::registerMSGER(MSGreciever* listener ){
m_Listeners.push_back(listener);
}
void MSGreciever::getMSGS(std::shared_ptr<msg> message) {
que.push_back(message);
}
MSGTYPE MSGreciever::peakatMSGS(int indextoPeak){
if(indextoPeak < que.size()){
return que[indextoPeak]->m_type;
}
}
void MSGreciever::handleMSGS(void * passedvar){
for (unsigned int i =0; i < que.size(); i++){
if( SentTo.matchMyID( que[i]->getTargetID()) == true ) {
que[i]->update(passedvar);
}
}
if ( que.empty() == false){
que.pop_back();
}
}
bool MSGreciever::handleMSG(void * passedvar){
if(que.empty() == false){
if(SentTo.matchMyID( que[que.size()]->getTargetID()) == true){
que[que.size()]->update(passedvar);
que.pop_back();
}
}
return que.empty();
}
and the allocation code inside of the behaviour class looks like
m_mailman.sendMSG is a Message Dispatcher
i have tried useing std::make_shared<msg>( new PhysicsMSG(...)) and that didnt work either
Code: Select all
m_mailman.sendMSG(std::make_shared<msg>(PhysicsMSG(Velocity, m_time.getDelta(), m_Target, m_Mine)));
m_mailman.sendMSG(std::make_shared<msg>(AnimationMSG(15, 3, state::animated, m_Target, m_Mine)));
PS: if it looks like i dont know what i am doing. i feel like i don't either.