i know you cannot understand anything from the title and i am sorry but i don't know how to say it because it's a little complicated, so i won't give details of my problem, i hope you can understand from the code

classB.h:

#ifndef CLASSB_H
#define CLASSB_H

class MainClass;      // so we can declare a pointer of class B

class SecClass
{
public:
MainClass *m_MainClass;

SecClass( );
~SecClass( );
};

classB.cpp

#include "classB.h"
#include "classA.h"

//
// A
//

SecClass :: SecClass( MainClass nMainClass )
{
    m_MainClass = nMainClass;
}

SecClass :: ~SecClass( )
{
    m_MainClass->someFunct( );
}

classA.h:

#ifndef CLASSA_H
#define CLASSA_H

class SecClass;      // so we can declare a pointer of class B

class MainClass
{
public:
SecClass *m_SecClass;
int m_ID;

MainClass( );
~MainClass( );
bool Update( );
void someFunct( ) { }
};

#endif

classA.cpp

#include <iostream>
#include "classA.h"
#include "classB.h"

//
// A
//

MainClass :: MainClass( )
{
    m_SecClass = new SecClass( this );
}

MainClass :: ~MainClass( )
{
    delete m_SecClass;
}

bool MainClass :: Update( )
{
    // do stuff...
    
    if( ... )
        return true;

    return false;
}

void main( )
{
    MainClass *gMainClass = new MainClass( );
    
    while( gMainClass->Update( ) )
    {
        // main program loop
    }

    delete gMainClass;    // this will crash
}

so, i'll explain
MainClass creates a new instance of a SecClass
The SecClass creates a pointer to the main class( to access some funct/values )
when the main class destructor is called, the program deletes the SecClass too, but when the destructor of SecClass is called it occures a crash because it tryes to call a fuction of the main class whitch has been destroyed...

how can i avoid this unhappy case?
gMainClass = NULL; and checking for null class pointer in the SecClass destructor si not an option since we'd cause a memory leak

The main class object will be the last that is destroyed. That is not your problem. Your problem is that you did not create copy constructors and assignment operators. Whenever you have pointer-members in a class you should create default- and copy constructors, assignment and destructors. Your function

SecClass :: SecClass( MainClass nMainClass )

uses a MainClass parameter as by-value which will create an anonymous copy of the object you pass to it. It invokes the copy-constructor which is the autogenerated-flat-copy one that is always created if you don't create a copy constructor yourself. This flat copy treats pointers as (integer) values and does not copy the objects it points to. When your destructor of MainClass is called on the anonymous object it deletes what it points to. No problem up to here, but when your original object goes out of scope the destructor tries to delete the object that was already deleted and crashes.
So create the assignment and copy constructor and see how you get on...

i am sorry, this:

SecClass :: SecClass( MainClass nMainClass )

was meant to be this:

SecClass :: SecClass( MainClass *nMainClass )

i already have the assigment constructor, as for the copy constuctor, not(because i don't need it). in the SecClass constructor it was meant to pass the address of the MainClass, so the SecClass can access MainClass object and functions

and as for the crash, i am very sure that it crashes when the SecClass tryes to access on member of the MainClass after calling the MainClass destructor, i used breakpoints to test this...

Edit: the real code is a lot more complex, this was just an example witch i used to express my problem easy

Edited 5 Years Ago by dospy: n/a

I think you need to include what your 4 standard methods do for each of your classes in your post. For example I believe that SecClass should use flat-versions, i.e. do not any deletes for the mainClass whereas MainClass should delete, and deep-copy the SecClass members, but we need to see what you are doing there to help you.

The general rule is that the lifetime of an object ends as soon as the body of the destructor is entered. This would normally mean your code is "illegal". However, it technically isn't entirely. You should still be able to call member functions or access POD data members fairly safely (it is against good coding practices, but it shouldn't crash).

The only reason that I see why it would crash is if: you call a virtual function of the MainClass. Then, it should crash. If you call a virtual function, you should know that the virtual table of the object is no longer valid when you enter the body of the destructor and you will basically be dereferencing a null-pointer.

The general rule is that the lifetime of an object ends as soon as the body of the destructor is entered. This would normally mean your code is "illegal". However, it technically isn't entirely. You should still be able to call member functions or access POD data members fairly safely (it is against good coding practices, but it shouldn't crash).

The only reason that I see why it would crash is if: you call a virtual function of the MainClass. Then, it should crash. If you call a virtual function, you should know that the virtual table of the object is no longer valid when you enter the body of the destructor and you will basically be dereferencing a null-pointer.

there is no virtual fuction in the MainClass, but thx for that notification, i didn't know that virtual function/object are no longer valid after calling the destructor.

I think you need to include what your 4 standard methods do for each of your classes in your post. For example I believe that SecClass should use flat-versions, i.e. do not any deletes for the mainClass whereas MainClass should delete, and deep-copy the SecClass members, but we need to see what you are doing there to help you.

no, the SecClass is accessing just a normal fuction of the MainClass, it does not delete any of the object of it either.

the source code is not private, i am just editting an open source program(because i use that program and editting it makes it more suitable for me and i also like to programm :D), just the code is too big(about 5000 lines on cpp files and 100 on headers) and that's why i prefered not including it into the post

this program is a host bot, the MainClass is the class that deals with user input and general configs, the SecClass is a class witch takes care of a running game
the program is working this way: the main loop is running(witch executes the MainClass Update function), checking for input in the console, if the input matches a certain command, it creates an instance of SecClass(to run a game)...
the main class also takes care of the UDP connections and when the SecClass is destroyed it needs to access the socket to broadcast a Game Decreate message.

hmm, just now it run trhough my mind that the destructor of the SecClass could try to access an pointer to a class that deals with connections after it was deleted
it could be possible if the connection class is deleted before the SecClass in the MainClass destructor, i am going to check right now.
yes, that was the problem.

thx to all of you who replied.

Edited 5 Years Ago by dospy: n/a

The more typical way to handle these situations is to have a "finalize" function in the SecClass that the MainClass can call before "really" destroying itself. This way, the responsibility is on the MainClass to make sure that "finalize" is called when the MainClass is still fully-functional. Then, the destructor of SecClass no longer has to do this trickery (and, this also works whether the SecClass object is held by pointer or by value in the MainClass).

The more typical way to handle these situations is to have a "finalize" function in the SecClass that the MainClass can call before "really" destroying itself. This way, the responsibility is on the MainClass to make sure that "finalize" is called when the MainClass is still fully-functional. Then, the destructor of SecClass no longer has to do this trickery (and, this also works whether the SecClass object is held by pointer or by value in the MainClass).

thx, i'll take into account your advice

Edited 5 Years Ago by dospy: n/a

This question has already been answered. Start a new discussion instead.