heres some clue about the life-cycle of the Clients* object
client connects to the server...Code:CTCPSocket *NewSocket = pdcc->m_CTCPS->Accept( (fd_set *)&fd ); if( NewSocket ) { NewSocket->NoDelay(true); Clients *client = new Clients(NewSocket, pdcc); client->m_Identified = false; client->m_Chat = pdcc->m_DefaultChat; CONSOLE_Print("[SERVER] New client has connected to the server [ " + NewSocket->GetIPString( ) + "]."); m_Clients.push_back(client); }
client connection lostCode:for(vector<Clients*> :: iterator i = m_Clients.begin( ); i != m_Clients.end( );) { if( (*i)->m_Socket && (*i)->m_Socket->GetConnected( ) && !(*i)->m_Socket->HasError( ) ) { (*i)->m_Socket->SetFD(&fd, &send_fd, &nfds); nfds++; i++; } else { cout << "A client connection was lost." << endl; CleanUpUser((*i)); i = m_Clients.erase( i ); } }
dereferrencing the instance safely laterCode:void CPDC :: CleanUpUser(Clients *client) { client->m_DeleteTime = GetTime(); client->m_Deleting = true; m_ClientsDeleting.push_back(client); }
seg fault happens on the CBoolExpr( ) function that validates the ClientCode:for(vector<Clients*> :: iterator i = m_ClientsDeleting.begin( ); i != m_ClientsDeleting.end( ); ) { if( (*i) ) { if( GetTime() - (*i)->m_DeleteTime >= 240 ) { delete *i; (*i) = NULL; i = m_ClientsDeleting.erase( i ); } else i++; } else i = m_ClientsDeleting.erase( i ); }
i use that whenever a client sends a 'special' package and when the client disconnects ( we got chat channels that remove Clients if their delete flag is on. )
Code:for(vector<CChat*> :: iterator i = m_ChatRooms.begin( ); i != m_ChatRooms.end( );) { if(!(*i)) i = m_ChatRooms.erase( i ); else { for(vector<Clients*> :: iterator j = (*i)->m_Users.begin( ); j != (*i)->m_Users.end( );) { if( (*j) && !CBoolExpr( (*j) ) ) { Event_UserLeft2( (*j), (*i) ); j = (*i)->m_Users.erase( j ); } else j++; } i++; } }
the socket wrapper
i dont use memcpy( ) or malloc( )Code:class CSocket { protected: SOCKET m_Socket; struct sockaddr_in m_SIN; bool m_HasError; int m_Error; public: CSocket( ); CSocket( SOCKET nSocket, struct sockaddr_in nSIN ); ~CSocket( ); virtual BYTEARRAY GetPort( ); virtual BYTEARRAY GetIP( ); virtual string GetIPString( ); bool HasError( ); virtual int GetError( ) { return m_Error; } virtual string GetErrorString( ); virtual void SetFD( fd_set *fd, fd_set *send_fd, int *nfds ); virtual void Allocate( int type ); virtual void Reset( ); }; class CTCPSocket : public CSocket { protected: bool m_Connected; private: string m_RecvBuffer; string m_SendBuffer; uint32_t m_LastRecv; uint32_t m_LastSend; public: CTCPSocket( ); CTCPSocket( SOCKET nSocket, struct sockaddr_in nSIN ); virtual ~CTCPSocket( ); virtual void Reset( ); bool GetConnected( ); virtual string *GetBuffer( ) { return &m_RecvBuffer; } virtual void PutBytes( string bytes ); virtual void PutBytes( BYTEARRAY bytes ); virtual void ClearRecvBuffer( ) { m_RecvBuffer.clear( ); } virtual void ClearSendBuffer( ) { m_SendBuffer.clear( ); } virtual uint32_t GetLastRecv( ) { return m_LastRecv; } virtual uint32_t GetLastSend( ) { return m_LastSend; } virtual void DoRecv( fd_set *fd ); virtual void DoSend( fd_set *send_fd ); virtual void Disconnect( ); virtual void NoDelay( bool noDelay ); };
and also i don't use arrays because arrays are evil.
just memset
Code:CSocket :: CSocket( ) { m_Socket = INVALID_SOCKET; memset( &m_SIN, 0, sizeof( m_SIN ) ); m_HasError = false; m_Error = 0; }




Reply With Quote
