destructoren



  • ist das eigentlich objekt noch wärend der ausführung des destructors gültig? Alsoi zeigt this noch auf was gültiges? Eigentlich schon oder? Ich bin gerade so verzweifelt das ich echt nach jeder möglichkeit suche warum er dort segfaultet wo er segfaultet.



  • Ja, während der Abarbeitung des Dtors existiert dein Objekt noch. Das wird erst am Ende ins Daten-Nirvana verbannt (genauer gesagt: nachdem dein eigener Dtor-Code abgearbeitet wurde, werden noch die Member- und die Basis-Dtoren aufgerufen).

    Für die Hilfe bei der Fehlersuche könntest du ja etwas Code angeben, wo es gekracht hat.



  • Sagen wir es mal so, welchen Sinn hätte ein Destruktor wenn das Objekt (sprich der this Pointer) nicht mehr gültig wäre? Genau, sogut wie keinen 😉

    Aber hier wird dir niemand den Kopf abreissen, wenn du ein paar Codeschnipsel mit dem entsprechenden Problem/Fehler preisgibst. Ansonsten garantiere ich für nichts 😛



  • Fedaykin schrieb:

    ...Alsoi zeigt this noch auf was gültiges?...

    ... allerdings "funktionieren virtuelle Funktionsaufrufe nicht mehr".

    Gruß,

    Simon2.


  • Mod

    Simon2 schrieb:

    Fedaykin schrieb:

    ...Alsoi zeigt this noch auf was gültiges?...

    ... allerdings "funktionieren virtuelle Funktionsaufrufe nicht mehr".

    Gruß,

    Simon2.

    Nicht-Funktionieren ist keine keine Kategorie des Standards. Deute ich um in undefiniertes Verhalten, so ist die Behauptung grundsätzlich falsch. Undefiniert ist es dann, wenn eine Funktion aufgerufen ist, die für den gegenwärtigen Typ des Objektes rein-virtuell ist. Ein Destruktor wird auf ein vollständig konstruiertes Objekt aufgerufen, nach Beendigung des Destruktors hört das Objekt auf zu existieren und zerfällt in seine Member und Basisklassenobjekte.



  • camper schrieb:

    ...Nicht-Funktionieren ist keine keine Kategorie des Standards. ...

    Schön ausgedrückt ! 😃
    Ich hatte gerade keine Zeit/Gelegenheit, das zu konkretisieren, wollte das Thema aber in dem Zusammenhang anschneiden und vertraute darauf, dass jemand wie Du es vernünftig (und viel besser als ich es könnte) darstellen würde ...

    Danke,

    Sipmon2.



  • ok ihr habt den code gewollt. Der ist mittlerweile vom vielen rum probieren unsauber geworden aber das sauber machen werd ich wohl erst wenns wirklich läuft

    **
    *@file CNetInterface.hpp holds the implementation of the CNetInterface classes 
    *
    *@author Heiko Weiß aka Cassandra Fjurin    
    *@version 1.0
    */
    
    #include "netinterface/CReceiver.hpp"
    #include "netinterface/CBasicClientCommand.hpp"
    #include "netinterface/CBasicServerCommand.hpp"
    #include "netinterface/protocol/ClientCommands.hpp"
    
    CReceiver::CReceiver( CNetInterface * conn, CNetInterface::RECEIVEDCOMMANDS * rQueue ) : connection( conn ), receivedQueue( rQueue )
    {
        buffer = new CByteBuffer(1000);
        //create the two mutexes for secure access to the buffer
        pthread_mutex_init( &rQMutex, NULL);
        pthread_mutex_init( &bufferMutex, NULL);
        receivedQueue->clear();
    
        rlrunning = false;
        edrunning = false;
        recvOK = false;
        encodeOK = false;
    
    }
    
    CReceiver::~CReceiver()
    {
        try
        {
            rlrunning = false;
            edrunning = false;
            shutdown(connection->m_read_socket,SHUT_RD);
            std::cout<<"destructing receiver"<<std::endl;
            pthread_cancel( encode_thread );    
            std::cout<<"encode thread was cancelled"<<std::endl;
            pthread_cancel( receive_thread );
            int error;
            std::cout<<"start to destroy the mutexes"<<std::endl;
            error = pthread_mutex_destroy( &rQMutex );
            if ( error )std::cout<<"error while destroying rQMutex in CReceive"<<std::endl;
            error = pthread_mutex_destroy( &bufferMutex );
            if ( error )std::cout<<"error while destroying bufferMutex in CReceive"<<std::endl;
            std::cout<<"receiver destructed"<<std::endl;    
            delete buffer;    
        }
        catch (std::exception const& e)
        {
            //std::cerr << e.what () << std::endl;
        }
        catch (...)
        {} 
    }
    
    bool CReceiver::start()
    {
        pthread_attr_t pattr;
        pthread_attr_init( &pattr);
        pthread_attr_setdetachstate( &pattr, PTHREAD_CREATE_DETACHED );
        bool ok = true;
        if ( pthread_create( &receive_thread, &pattr, (void*(*)(void*))&receive_loop, this ) != 0 )
        {
            std::cerr << "Read-S-Nummer: " << connection->m_read_socket << " error on receive thread creation (receiver loop): " << strerror( errno ) << std::endl;
            ok = false;
        }
        pthread_attr_t pattr2;
        pthread_attr_init( &pattr2);
        pthread_attr_setdetachstate( &pattr2, PTHREAD_CREATE_DETACHED );    
        if ( ok & pthread_create( &encode_thread, &pattr2, (void*(*)(void*))&encode_data_loop, this ) != 0 )
        {
            std::cerr << "Read-S-Nummer: " << connection->m_read_socket << " error on receive thread creation (encode loop): " << strerror( errno ) << std::endl;
            ok = false;
        }
    
        return ok; 
    }
    
    void CReceiver::stop()
    {
        rlrunning = false;
        edrunning = false;
    }
    
    unsigned char CReceiver::getUnsignedCharFromBuffer()
    {
        int numtrys = 0;
        timespec waittime; 
        waittime.tv_sec = 0;
        waittime.tv_nsec = 50000000; //50 ms; 
        while ( buffer->dataAvailable() < 1 && numtrys < 20 )
        {
            if ( !connection->online )
            {
                stop();
                return 0;
            }
            numtrys++;
            try
            {
                //pthread_setcancelstate(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
                nanosleep(&waittime,NULL);
                //pthread_setcancelstate(PTHREAD_CANCEL_DEFERRED, NULL);
            }
            catch (std::exception e)
            {
                std::cerr<<"disturbed during sleeping getUnsignedCharFromBuffer():"<<e.what()<<std::endl;
            }
            catch(...){}
            pthread_testcancel();
        }
        if ( buffer->dataAvailable() < 1 )
        {
            std::cerr<<"error while receiving data not enough data... eror in connection"<<std::endl;
            connection->closeConnection();
        }
        else if ( connection->online )
        {
            pthread_testcancel();
            unsigned char ret;
            pthread_mutex_lock( &bufferMutex );
            // std::cout<<"(getbyte) buf mut locked"<<std::endl;
            ret = buffer->getByte();
            pthread_mutex_unlock( &bufferMutex );
            //std::cout<<"(getbyte) buf mut unlocked"<<std::endl;
            return ret;
        }
        pthread_testcancel();
        return 0;
    }
    
    std::string CReceiver::getStringFromBuffer()
    {
        unsigned char len = getUnsignedCharFromBuffer();
        if (len>250) len = 250;
        std::string ret="";
        unsigned char resolved;
        for ( int i = 0; i < len; ++i)
        {
            resolved = getUnsignedCharFromBuffer();
            ret.append( 1, resolved);
        }
        return ret;
    }
    
    int CReceiver::getIntFromBuffer()
    {
        int ret = getUnsignedCharFromBuffer() << 24;
        ret = ret | (getUnsignedCharFromBuffer() << 16);
        ret = ret | (getUnsignedCharFromBuffer() << 8);
        ret = ret | getUnsignedCharFromBuffer();
        return ret;
    }
    
    short int CReceiver::getShortIntFromBuffer()
    {
        short int ret = getUnsignedCharFromBuffer() << 8;
        ret = ret | getUnsignedCharFromBuffer();
        return ret;
    }
    
    void * CReceiver::encode_data_loop( CReceiver * receiver )
    {
       // pthread_cleanup_push(pthread_mutex_unlock,(void*)&receiver->rQMutex);
    
        receiver->encodeOK = true;
                //create waittime struct so the thread waits for 20 ms 
                timespec waittime; 
                waittime.tv_sec = 0;
                waittime.tv_nsec = 20000000; //50 ms;            
                receiver->setedrunning(true);
    #ifdef _NO_LOGIN_BYTE_            
                bool first = true;
    #endif            
                while ( receiver->getedrunning() )
                {
                    if ( receiver->dataAvailable() > 0 )
                    {
    #ifdef _NO_LOGIN_BYTE_  
                        if ( first )
                        {
                            boost::shared_ptr<CLoginCommandTS> lgCommand( new CLoginCommandTS() );
    
                            lgCommand->clientVersion = receiver->getShortIntFromBuffer();
                            lgCommand->loginName  = receiver->getStringFromBuffer();
                            lgCommand->passwort = receiver->getStringFromBuffer();
                            try
                            {
                                std::cout<<"received login command!"<<std::endl;
                                pthread_mutex_lock( &(receiver->rQMutex) );
                                receiver->receivedQueue->push_back( lgCommand );
                                std::cout<<"pushed back login command!"<<std::endl;
                                pthread_mutex_unlock( &(receiver->rQMutex) );
                            }
                            catch( std::exception const &e )
                            {
                               // std::cerr<<"exception during mutex locking: "<<e.what()<<std::endl;
                            }
                            catch (...) {} 
                            first = false;
                        }
                        else
    
    #endif              
                        {
                        unsigned char cmdid = receiver->getUnsignedCharFromBuffer();
                        // std::cout<<"receiveing commandid: "<< std::hex << static_cast<int>(cmdid) << std::dec<<std::endl;
                        //special handling for start end commands, we need to store the direction which is coded in the definition byte
                        boost::shared_ptr<CBasicClientCommand>cmd;
                        if ( (cmdid >= PMOVERSTART_TS) && (cmdid <= PMOVEREND_TS))cmd = boost::shared_ptr<CBasicClientCommand>( new CMoverActionTS(cmdid-PMOVERSTART_TS));
                        else if ( (cmdid >= IMOVERSTART_TS) && (cmdid <= IMOVEREND_TS)) cmd = boost::shared_ptr<CBasicClientCommand>(new CIMoverActionTS(cmdid-IMOVERSTART_TS));
                        else if ( (cmdid >= CPUSHRSTART_TS) && (cmdid <= CPUSHREND_TS)) cmd = boost::shared_ptr<CBasicClientCommand>(new CPushActionTS(cmdid-CPUSHRSTART_TS));
                        else if ( (cmdid >= PSPINRSTART_TS) && (cmdid <= PSPINREND_TS)) cmd = boost::shared_ptr<CBasicClientCommand>(new CPSpinActionTS(cmdid-PSPINRSTART_TS));
                        else cmd = CCommandFactory::get()->getCommand( cmdid );
                        if ( cmd )
                        {
                            try 
                            {
                                cmd->receiveData( receiver );
                                pthread_mutex_lock( &(receiver->rQMutex) );
                                receiver->receivedQueue->push_back( cmd );
                                pthread_mutex_unlock( &(receiver->rQMutex) );
    
                            }
                            catch ( std::exception const &e )
                            {
                                //std::cerr<<"exception during mutex locking: "<<e.what()<<std::endl;
                            }
                            catch (...) {} 
                        }
                        else
                        {
                            try
                            {
                                std::cout<<"Error receiving the command with id: "<< std::hex << cmdid<<" command was not in factory list!"<<std::dec<<std::endl;
                            }
                            catch( std::exception const &e )
                            {
                                //std::cerr<<e.what();
                            }
                            catch (...) {} 
                        }
                        pthread_testcancel();
                        }
                    }
                    else
                    {
                        try
                        {
                            //pthread_setcancelstate(PTHREAD_CANCEL_ASYNCHRONOUS, NULL);
                            nanosleep(&waittime,NULL);
                            //pthread_setcancelstate(PTHREAD_CANCEL_DEFERRED, NULL);
                        }
                        catch ( std::exception e )
                        {
    
                        }
                        pthread_testcancel();
                    }
                 }
                 //pthread_cleanup_pop( 0 );
                receiver->encodeOK = false;
                pthread_exit( 0 );
                return NULL;
    }
    
    void * CReceiver::receive_loop( CReceiver * receiver )
    {
                receiver->recvOK = true;
                //create waittime struct so the thread waits for 20 ms 
                timespec waittime; 
                waittime.tv_sec = 0;
                waittime.tv_nsec = 50000000; //20 ms;
    
                //stores how often the data can't be stored in the buffer
                //if this number to large the server seems to be crashed and the 
                //connection will be canceled
                receiver->setrlrunning( true );
                //pthread_cleanup_push(pthread_mutex_unlock,(void*)&receiver->bufferMutex);
                int recvinactive = 0;
                while ( receiver->getrlrunning() )
                {
                    //there is space in the buffer
                    if ( receiver->buffer->getNumberToWrite() > 0 && receiver->connection->online)
                    {
                            //last buffer saved so we can receive new data
                            int count = 0;
                            try
                            {
                                count = recv( receiver->connection->m_read_socket, receiver->buffer->getWritingPos(), receiver->buffer->getNumberToWrite(),MSG_NOSIGNAL);
                                pthread_testcancel();
                                pthread_mutex_lock( &receiver->bufferMutex );
                                receiver->buffer->bytesWritten( count );
                                pthread_mutex_unlock( &receiver->bufferMutex );
                            }
                            catch ( std::exception const &e )
                            {
                                std::cerr<<"error in reive loop: "<<e.what()<<std::endl;
                            }
                            if ( count < 1 )
                            {
                                try
                                {
                                    std::cout<<"count < 1 closing connection!"<<std::endl;
                                    if ( receiver->connection->online)receiver->connection->closeConnection();
                                }
                                catch ( std::exception const &e )
                                {
                                    //std::cerr<<e.what()<<std::endl;
                                }
                                catch (...) {} 
                            }
    
                    }
                    else
                    {
                        if ( recvinactive > 100 )receiver->connection->closeConnection(); 
                        recvinactive++;
                        try
                        {
                            nanosleep(&waittime,NULL);
                        }
                        catch ( std::exception e )
                        {
                        }
                        pthread_testcancel();
                    }
    
                }
                try
                {
                    std::cout<<"receiver end!"<<std::endl;
                }
                catch( std::exception const &e )
                {
                    //std::cerr<<e.what()<<std::endl;
                }
                catch (...) 
                {
                }; 
                //pthread_cleanup_pop( 0 );
    
                receiver->recvOK = false;
                pthread_exit( 0 );
                return NULL;
    }
    

    wenn er wirklich segfaultet dann in Zeile 38 aber der debugger zeigt mir auch noch andere fehler an. ich mach gleich mal nen querverweise ins andere Forum



  • Fedaykin schrieb:

    ok ihr habt den code gewollt....

    Nö:

    CStoll schrieb:

    ...etwas Code angeben, wo es gekracht hat.

    und

    Baracke schrieb:

    ...ein paar Codeschnipsel ...

    :p

    Ohne die Klassendefinitionen komme ich nicht weiter ... und es hilft mir auch nicht, Code zu sehen, der mit dem Thema nichts zu tun hat. 😉

    Gruß,

    Simon2.



  • wirklich krachen tut es hier:

    CReceiver::~CReceiver()
    {
        try
        {
            rlrunning = false;
            edrunning = false;
            shutdown(connection->m_read_socket,SHUT_RD);
            std::cout<<"destructing receiver"<<std::endl;
            pthread_cancel( encode_thread );    
            std::cout<<"encode thread was cancelled"<<std::endl; //<-- diese Zeile ist noch im out file zu lesen
            pthread_cancel( receive_thread );
            int error;
            std::cout<<"start to destroy the mutexes"<<std::endl; //<-- die hier nicht mehr
            error = pthread_mutex_destroy( &rQMutex );
            if ( error )std::cout<<"error while destroying rQMutex in CReceive"<<std::endl;
            error = pthread_mutex_destroy( &bufferMutex );
            if ( error )std::cout<<"error while destroying bufferMutex in CReceive"<<std::endl;
            std::cout<<"receiver destructed"<<std::endl;    
            delete buffer;    
        }
        catch (std::exception const& e)
        {
            //std::cerr << e.what () << std::endl;
        }
        catch (...)
        {}
    }
    

    Also zwischen den beiden <-- machts also bumm *gg*
    und daher hatte ich noch die den rest .... den der thread selber arbeitet im grunde das hier ab

    while ( receiver->getrlrunning() )
                {
                    //there is space in the buffer
                    if ( receiver->buffer->getNumberToWrite() > 0 && receiver->connection->online)
                    {
                            //last buffer saved so we can receive new data
                            int count = 0;
                            try
                            {
                                count = recv( receiver->connection->m_read_socket, receiver->buffer->getWritingPos(), receiver->buffer->getNumberToWrite(),MSG_NOSIGNAL);
                                pthread_testcancel();
                                pthread_mutex_lock( &receiver->bufferMutex );
                                receiver->buffer->bytesWritten( count );
                                pthread_mutex_unlock( &receiver->bufferMutex );
                            }
                            catch ( std::exception const &e )
                            {
                                std::cerr<<"error in reive loop: "<<e.what()<<std::endl;
                            }
                            if ( count < 1 )
                            {
                                try
                                {
                                    std::cout<<"count < 1 closing connection!"<<std::endl;
                                    if ( receiver->connection->online)receiver->connection->closeConnection();
                                }
                                catch ( std::exception const &e )
                                {
                                    //std::cerr<<e.what()<<std::endl;
                                }
                                catch (...) {}
                            }
    
                    }
                    else
                    {
                        if ( recvinactive > 100 )receiver->connection->closeConnection();
                        recvinactive++;
                        try
                        {
                            nanosleep(&waittime,NULL);
                        }
                        catch ( std::exception e )
                        {
                        }
                        pthread_testcancel();
                    }
    
                }
    

    also muss es irgendwo dort mal in die hose gehen, vermute ich. Wissen tu ichs halt nicht weil es könnte nen seiteneffekt von wo ganz anders her kommen. Genau das ist das problem beim multi threading.

    Das nächste problem ist halt. Das es 99 mal gut geht und irgendwann mal nicht.
    Benutze ich einen debugger (gdb) geht es zu 99 % in die hose und das an den wildesten stellen die hier wohl kaum was damit zu tun haben. *schultern zuck*

    und hier noch die definitionen

    class CReceiver
    {
        public:
    
            bool rlrunning; /*<stores if the receive loop thread is running and all is ok*/
            bool edrunning; /*<stores if the encode data thread is running*/
    
            /**
            *constructor
            *@param conn the connection from which the data is received
            *@param rQueue the receive queue to which the received commands should be stored
            */
            CReceiver( CNetInterface * conn , CNetInterface::RECEIVEDCOMMANDS * rQueue );
            ~CReceiver();
    
            /**
            *starts the current threads
            */
            bool start();
    
            /**
            *stops the current threads
            */
            void stop();
    
            /**
            *reads an unsigned char from the connection
            *@return the uchar which was red
            */
            unsigned char getUnsignedCharFromBuffer();
    
            /**
            *reads a String from the connection
            *@return the string which was red.
            */
            std::string getStringFromBuffer();
    
            /**
            *@param reads a int from the connection
            *@return the int which was red
            */
            int getIntFromBuffer();
    
            /**
            *reads a short int from the connection
            *@return the short int which was red
            */
            short int getShortIntFromBuffer();
    
            /**
            *function which checks how much data can be red from the buffer
            *@return a integer value how much data is stored in the buffer
            */
            uint16_t dataAvailable(){return (buffer->dataAvailable());}
    
            pthread_mutex_t rQMutex; 
    
        protected:
    
            //1000 byte large bytebuffer
            CByteBuffer * buffer;
    
            pthread_mutex_t bufferMutex; /*<mutex to protect the buffer*/ 
    
            CNetInterface * connection; /*<the connection to the player*/
    
            CNetInterface::RECEIVEDCOMMANDS * receivedQueue; /*<pointer to the queue which holds the received commands*/
    
            pthread_t receive_thread; /*<Thread which receives data and stores them in the buffer*/
            pthread_t encode_thread; /*<Thread wich encodes the data in the buffers to commands*/
    
            /**
            *function for the receive thread which stores data from the incoming transfer to a buffer
            *looks every x ms in the socket and stores the data in a buffer.
            */
            static void* receive_loop( CReceiver * receiver );
    
            /**
            *function which checks the buffer every n ms and looks if a new command has arrived
            *if a command has arrived the data is red from the buffer
            */
            static void * encode_data_loop( CReceiver * receiver );
    };
    


  • Ein kurzer Überblick sagt mir: Du hast die "Rule of three" nicht beachtet - wer einen eigenen Dtor benötigt, braucht typischerweise auch einen Copy-Ctor und operator=. Das Default-Verhalten dieser Methoden ist eine flache Kopie aller Member, so daß die Kopie die selben Ressourcen verwendet wie das Original. Und da der Dtor diese Ressourcen wieder freiräumt, hat das langlebigere Objekt nur noch Müll-Daten, wenn es zerstört wird.

    (normalerweise macht sich das als "double-free" bemerkbar, aber bei dir wurde anscheinend einer der 'pthread_cancel()'-Aufrufe auf einen nicht mehr exisiterenden Thread losgelassen)



  • Das ist doch schon mal ein ansatz. Danke. Werd das mal versuchen.


Log in to reply