Advertisement

SDL_net help, please. Client crashing.

Started by January 12, 2005 11:19 AM
2 comments, last by kenwi 19 years, 8 months ago
Hello. I'm using SDL_net (I'm running linux as well.) for writing a server and client application. What I want to do is having a server sending data to the client. First the server is started, it then waits for the client to connect. The client connects to the server and the server let the client in. Server then waits for the client to request data from the server. When requested, the server then sends data to the client which recieves and should print out the data. The data in this case is a list of coordinates (which it gets from a mysql database) The server seems to be working fine. It get info from the mysql-database alright (it can print out the data from mysql-database) and I also believe it sends the data just fine. But, when I try printing out the data from the client - it crashes. I'll try to describe how it works; As I said, the (coordinates)data is stored in a list.

class cData 
{
	public: 
		cData()
		{ 
			id = 0;
			message = NULL; 
		};
		
		int id;
		list<cPoint *> pList;  // stores coordinates.
};
The actual data I put into the list.

class cPoint
{
	public:
		cPoint() { }
    
	   cPoint( int id, float x, float y ) 
	   { 
		   this->id=id;
		   this->x=x; 
		   this->y=y;
	   }		
		float x, y, z;
		int id;
};
When I want to put the data into the list (from the mysql-database) I put it into the list like this. The packet is called starPacket, it will be sent to the client later, on request from the client.

cData *starPacket = new cData;
while( (row = mysql_fetch_row(result)) )
{
	cPoint *star;
	star = new cPoint( atoi(row[0]), atof(row[1]), atof(row[2]) );
	starPacket->pList.push_back( star );
	star = NULL;
	delete star;
}
So, when the client connects, it send a "packet" to the server - which then check the variable "id" for how to deal with the packet. In this case, if the client sends a packet with id 1 it means the client want the list of coordinates. The server then tries to send the list that were populated earlier. It also tags the new packet with a new id so I can check if the packet is sent to the client. I also (for debugging purposes) print out the last id i could fin d in the list and the packet id.

if( SDLNet_SocketReady((*li)->sock) )
{
	cData *packet = new cData();
	int result = SDLNet_TCP_Recv( (*li)->sock, packet, sizeof(cData) ); 
	if( result )
	{
		if( packet->id == 1 )
		{
			printf("Got a starmap query, guess we should send it..\n");
			starPacket->id = 1234;
			SDLNet_TCP_Send( (*li)->sock, starPacket, sizeof(cData) );
						
			list<cPoint *>::iterator i;
			i = starPacket->pList.end();
			i--;
			printf("Last id: %i, packet id: %i\n", (*i)->id, starPacket->id );
		}
	}
}
There is no error so far, and everything seems fine. So what I'm sending is the whole object with all its variables (and hopefully the list in the class). With earlier tests with simple variables only, it has worked. But now as I'm trying to send the list - it fails. Now over to the client; The client gets connected to the server and everything seems fine. As mentioned earlier, it sends a packet to the server with id 1. This, as I said earlier means that it want the list from the server.

cData *packet = new cData();
packet->id = 1;	
SDLNet_TCP_Send( sock, packet, sizeof(cData) );
packet = NULL;
delete packet;
Now as the packet is sent to the client, the server sends back the object with the new id "1234" and hopefully the list. This is where things seem to fail. As you can see, the client makes a new object, recieves the packet from the server. I now try to set the iterator to the end of the list, minus one. And then print out the variable 'id', at this point - the client crashes and I dont know what's causing it. As you can see i print out the packet id just to make sure it recieves the packet. It seems like it does, cause it prints out the correct value (1234).

cData *packet = new cData();
int result = SDLNet_TCP_Recv( sock, packet, sizeof(cData) );
if( result )
{
	printf("Recieved packetid: %i\n", packet->id );
	
	list<cPoint *>::iterator li;
	li = packet->pList.end();
	li--;
	printf("%d\n", (*li)->id );
}
Now, I've also tried iterating trough the whole list but I get the same result. And I'm also certain that the server gets the data from the database (I tried printing out the starPacket data before sending to the client. I hope anyone can help me out here, it will be greatly appreaciated, I'm out of ideas of what to do. (Not quite, I suppose I could just use normal arrays but that is not the approach I'm searching for). Thanks in advance. EDIT: This is the output from the server and the client.

Server ready, waiting for connections..
Numready: 1
Accepted a connection from 192.168.1.101 port 8581
Got a starmap query, guess we should send it..
Last id: 52, packet id: 1234
Client:

bash-2.05b$ ./sdlclient 192.168.1.101 6666
Connected to server..
Sending packet with id 1..
Recieved packetid: 1234
Fatal signal: Segmentation Fault (SDL Parachute Deployed)
[Edited by - kenwi on January 12, 2005 11:40:23 AM]
i didnt read your entire post, but.. have you stepped through the client with a debugger and found the exact line it crashes on? this should help us a lot in helping you find the bug.
FTA, my 2D futuristic action MMORPG
Advertisement
another thing.. you seem to be sending an entire cData struct. the problem is this struct contains a std::list. you should not try sending a dynamic data type such as an STL container or string. this simply will not work since the object itself contains pointers which point to memory space for the program who is currently running it.

the other thing that jumped out at me was your allocate the cData dynamically, send() the data, and then delete the memory. this jumps out at me. im not sure how SDL works, but this seems like it could be a serious problem. what if SDL_net is threaded and doesnt send the packet immediately after you call send()? you fed it the memory address of your data, called send, and then delete the memory. Send() will then try to operate on deleted memory, which will quickly crash your app. try removing the call to delete to see if im right about that (although this will cause a leak; find a different way to send your data, e.g. copy the data into some static buffer and then send a chunk of that buffer).
FTA, my 2D futuristic action MMORPG
Thanks for posting and also for enlightening me. I'm only considering myself of a intermediate programmer (regarding to the allocation of memory, pointers and refferences etc.), but with you pointing out the mistakes I managed to send the data to the client. Not quite how I was originally intending to, but it works like a charm. Thanks again.

This topic is closed to new replies.

Advertisement