Assertion Failure

Started by
1 comment, last by Shannon Barber 23 years, 6 months ago
Found it! read on if you care... I hate assertion failures this could get long, click next forum quick! I have a simple CSocket program (well i guess its damn complicated, but simple as CSocket goes...) Everything works great, except i get an assertion failure (I've gotten these before when I tried to delete stuff off the stack ) It happens when it tried to delete a char pointer, but its definetly a pointer to heap memory. the chat packet sends successfully and shows up on the server's ListBox, and the program continues to run fine if I ignore the assertion failure... If I change it so that I dynamically allocate the packet (CPacket* packet= new CPacket) and don't delete it, I don't get the assertion failure, but then I leak (the compilers tells me and shows me the msg i typed in). After further investigation, it is a csocket problem, speficially with my serialize method
                    
class CPacket
	{
	public:
		CPacket();
		~CPacket();
		friend class CNetwork;
		int Chat(const CString&);
		Pack(const void*, long);
		void Serialize(CArchive& ar);

	protected:
		DWORD GenerateSerial(DWORD);
		DWORD GenerateECC();

	private:
		long length;
		PacketType packettype;
		DWORD serialnum;
		DWORD ecc;
		char* data;
	};


void CRecvSocket::OnReceive(int nErrorCode)
	{
	CPacket* packet = new CPacket;
	packet.Serialize(*arIn);
	//mynet->RecvPacket(*packet); //with this commented out, I still get the failure
	//CSocket::OnReceive(nErrorCode); //does nothing!

	delete packet;//Assertion failure on deleting data from the packet 

	}

//packet.Serialize(*arIn);
void CPacket::Serialize(CArchive& arc)
	{
	if (arc.IsStoring())
		{
		arc << length;
		arc << (long)packettype;
		arc << serialnum;
		int i=0;
		char c;
		while((c=data[i++])!=0)
			arc << c;
		arc << ecc;
		}
	else
		{//this part gets called

		long pt;
		arc >> length;
		arc >> pt; packettype = (PacketType) pt;
		arc >> serialnum;
		if(data)
			delete[] data;
		int n = length - sizeof(CPacket) + sizeof(data);
		//data = new char[n];//gets heap space here!

		data = new char[n+1];//this fixed it, oops forgot a char for the termination
		data[n]=0;//null terminate the string

		for(int i=0;i<n;i++)
			arc >> data<i>;
		arc >> ecc;
		DWORD cs = GenerateECC();
		if(cs!=ecc)
			{
			DWORD i=0;//something went horribly wrong!

			}
		}
	}
//mynet->RecvPacket(packet)
int CNetwork::RecvPacket(const CPacket& packet)
	{
	if(packet.packettype==PT_CHAT)
		ReceiveChat(packet);
	return(0);
	}
int CNetwork::ReceiveChat(const CPacket& packet)
	{
	if(packet.packettype!=PT_CHAT)
		return(-1);
	else
		{
		CString str(packet.data); //Is this the cause of the failure?

		int hr = myEngine->ReceiveChat(str);
		return(hr);
		}
	}

//myEngine->ReceiveChat(str);
int CGameEngine::ReceiveChat(const CString& str)
	{
//CListBox ChatBox;

	CString msg;
	if(ChatBox)
		{
str.LockBuffer();
		ChatBox->AddString(str); //this copies the contents of str right!?

str.UnlockBuffer();
		return(0);
		}
	else
		return(-1);
	}

CPacket::~CPacket()
	{
	if(data)
		{
		delete[] data;//BOOM! Assertion failure

		data=0;
		}
	}

                    
Edited by - Magmai Kai Holmlor on 10/7/00 12:27:31 PM Edited by - Magmai Kai Holmlor on 10/7/00 12:36:25 PM Edited by - Magmai Kai Holmlor on 10/7/00 12:37:41 PM
- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara
Advertisement
Your section that parses the incoming data has a few problems:

char *data;
the sizeof(data) = 4. You're getting the size of a pointer which on 32 bit platforms is 32 bits.

And what is causing the assertion, is that you are deleting data if it is non-null in the Serialize Function, but you are not setting it to NULL, so in the destructor, when you do if(data), you're getting true even though data is an invalid pointer.


And for a design tip, why not just switch to using CStrings? They're serializable, and will clean up your parsing code 100%. There's not much point in serializing everything, serializing to an array of char, then converting the character array into a CString when you could have just used the CString in the first place. Try re-writing it... it'll look better if nothing else. =)





Edited by - JonStelly on October 7, 2000 4:15:29 PM
I wanted to get 4, i wanted to get the size of char*. Just thought I should use the variable names...

I didn''t bother setting data to null ''cause I reallocate it right after I delete it.

The compiler just didn''t detect the unallocated memory write until I deleted the object that did the over-write. After I do the data = new[n]; I do data[n]=0; which is clearly wrong on review I changed it to data = new[n+1] and all is good.

I''m surprised the compile caught it at all, and yet wish it could have gave me a better clue as what caused the failure.

And I''m sending more stuff in the data payload than strings, other packets will contain player information and/or status updates, or even timer ticks. Could I still use CString?

I''ve added a PT_PING, PT_PONG, PT_PLAYER, etc.. since I fixed the bug
- The trade-off between price and quality does not exist in Japan. Rather, the idea that high quality brings on cost reduction is widely accepted.-- Tajima & Matsubara

This topic is closed to new replies.

Advertisement