udp error in VS2008

Started by
11 comments, last by Antheus 16 years, 1 month ago
I'm quite new at network programming, so maybe my question will sound silly. What happens is whenever my application exits, I get a a popup window from VS2008 saying:
Quote: Visual C++ 2008 Express Edition Windows has triggered a breakpoint in comm.exe. This may be due to a corruption of the heap, which indicates a bug in comm.exe or any of the DLLs it has loaded. This may also be due to the user pressing F12 while comm.exe has focus. The output window may have more diagnostic information."
This message happens only when I run the application in debug mode with the F5 key. If I start it without the debugger, then it exits without problems. Still, It can't really be a good sign to have a popup window like that in the debugger. I reduced my application to its simplest form. Here is a basic client that creates the bug. It doesn't require a server to reproduce the problem. But the server has the same problem.

#include <stdio.h>
#include <stdlib.h>
#include <winsock.h>
#include <process.h>

int main()
{
        WSADATA WSAData;
	if (WSAStartup (MAKEWORD (2, 2), &WSAData))
	{
		WSACleanup ();
		return (-1);
	}

	SOCKET s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
	int a = WSAGetLastError();
	struct sockaddr_in local_addr;
	memset (&local_addr, '\0', sizeof (local_addr));
	local_addr.sin_family = AF_INET;
	local_addr.sin_addr.s_addr = htonl (INADDR_ANY);
	local_addr.sin_port = htons (777);
	char nOn = 1;
    setsockopt (s, SOL_SOCKET, SO_BROADCAST, (const char *)&nOn, sizeof (nOn));
	if (bind (s, (struct sockaddr *)&local_addr, sizeof (local_addr)) == -1)
		return (-1);
	int aa = WSAGetLastError();


	if ( s != INVALID_SOCKET )
	{
		SOCKADDR_IN remote_addr;
		remote_addr.sin_family = AF_INET;
		remote_addr.sin_port = htons(8001);
		remote_addr.sin_addr.s_addr =  htonl(INADDR_BROADCAST);

		// send the data
		sendto(s, "Where are you?", 14, 0, (PSOCKADDR) &remote_addr, sizeof(SOCKADDR_IN));

	}

	closesocket( s );
	WSACleanup ();

}

I can remove the broadcast mode, it doesn't change a thing. I removed the error check for simplification, but all functions return without error and WSAGetLastError says everything is fine too. However, I don't get the error if I don't do the "sendto" or if I don't bind the socket. But I need the socket to be bound for the server to know where the message comes from. Do you have an idea of the cause of this problem? Thanks
Advertisement
You generally shouldn't bind to an arbitrary port on the client. Either set the port to 0 before you bind, or don't bind, and it will automatically bind when you do your first sendto().

The server will know where to send the packet from the address returned from recvfrom(). The port information for the client will be available there.

I would say, look at the parameters in your sendto call. Instead of passing a const char* straight in, trying passing in a char* mystring = "bleh" and do a strlen(mystring) for the data length param. That can help keep you out of trouble.
Why shouldn't I bind to an arbitrary port on the client? And what does it do if I set the port to 0? I tried with the same result has before. So what you're saying is if I don't bind, the first send to will automatically do it for me? If so, then the system will decide a port number for me and that port number would be valid for answering from the server. Is that right?

That might work. But then on the server, I have exactly the same problem. In that case, I really have to preset a port number and to bind it. Otherwise I won't know where to send the data to on the client. The server will do the same error has if it receives data in recvfrom when it's time to clean up the port or to exit the program.

Regarding the way to send data, I fully agree with you. It was made this way just for the demonstration.

Any other ideas?


not getting any problems when I tried the code.

Everything is better with Metal.

You're not getting it in the debugger? Are you using VS2008?

I tried WINSOCK_VERSION just to make sure, but since it's defined has:
#define WINSOCK_VERSION MAKEWORD(2,2) in WinSock2.h ( which I had to include instead of WinSock.h), it gave the same result...
Quote:Original post by vince35
Why shouldn't I bind to an arbitrary port on the client? And what does it do if I set the port to 0? I tried with the same result has before. So what you're saying is if I don't bind, the first send to will automatically do it for me? If so, then the system will decide a port number for me and that port number would be valid for answering from the server. Is that right?

That might work. But then on the server, I have exactly the same problem. In that case, I really have to preset a port number and to bind it. Otherwise I won't know where to send the data to on the client. The server will do the same error has if it receives data in recvfrom when it's time to clean up the port or to exit the program.

Regarding the way to send data, I fully agree with you. It was made this way just for the demonstration.

Any other ideas?



1. There's nothing technically wrong with binding the port manually on the client, it's just common practice to let the system do the work for you, and it ensures that you don't bind to a port that's already in use. Passing in 0, results in the same as not binding. The system gives you an available port and binds it for you. It's a good way to keep yourself out of trouble. Obviously on the server you must bind in order for clients to know which port to broadcast to.

2. *nod* How are you pulling the data back out on the server side? Can you post your recvfrom() call?

3. Since the sendto()/recvfrom() call are causing you the issues, I was suggesting looking at the parameters you're passing in. Seems the most likely case for some sort of mix-up. Since you're passing strings around, what are your project settings in terms of "character set"? (not set, multi-byte, unicode, etc...) Not sure if vc2008 changes the properties dialog on this, but it should be located in "Configuration Properties"->"General".

If you pass in a simple struct instead of a string, do you still get the issues?

example:
struct t_data{  int n;};...t_data data;data.n = 1;sendto(s, (char*)&data, sizeof(t_data), 0, (PSOCKADDR) &remote_addr, sizeof(SOCKADDR_IN));
Quote:setsockopt (s, SOL_SOCKET, SO_BROADCAST, (const char *)&nOn, sizeof (nOn));


Last parameter is passed by reference. It should be stack allocated variable. I'm not exactly sure what happens, but apparently it needs be an int, into which result is returned.

Quote:There are two types of socket options: Boolean options that enable or disable a feature or behavior, and options that require an integer value or structure. To enable a Boolean option, the optval parameter points to a nonzero integer. To disable the option optval points to an integer equal to zero. The optlen parameter should be equal to sizeof(int)


Try this:
int value = 1;int result = sizeof(nOn);setsockopt (s, SOL_SOCKET, SO_BROADCAST, (char *)&value, result);


The reason for this, compared to examples is:
typedef int                 BOOL
The BOOL in example code is not a 1 byte bool
That message may come from the heap checker.
To debug the native C++ heap using Visual Studio, there are several (non-portable) functions you can use. Read more at http://msdn2.microsoft.com/en-us/library/974tc9t1.aspx.

The first step is to #include <crtdbg.h> and <assert.h> and then add a heap validation after your call to GetMessage/PeekMessage and the end of your window proc:

assert(_CrtCheckMemory())

This will break when you're running in debug mode, if the heap has gotten corrupted through overwriting, a double free, or similar.
enum Bool { True, False, FileNotFound };
Hi David,

Here is the code I use for the receiving the data. I reformatted it a little bit for readability, but it's the same operations. In the code, I first check if there's something on the network before I do the recvfrom, but even without this code (which is useless in this simplified version), the problem remains.

  int nSocket = socket (PF_INET, SOCK_DGRAM, IPPROTO_UDP);  struct sockaddr_in stAddr;  memset (&stAddr, '\0', sizeof (stAddr));  stAddr.sin_family = AF_INET;  stAddr.sin_addr.s_addr = htonl (INADDR_ANY);  stAddr.sin_port = htons (nPort);  bind (nSocket, (struct sockaddr *)&stAddr, sizeof (stAddr);  while (1)  {    fd_set fdReadMap;    FD_ZERO (&fdReadMap); // Clear all file descriptors in set    FD_SET (nSocket, &fdReadMap); // Set a filedescriptor in a set    // select : Monitor read, write, and exception status    rval = select (nSocket + 1, &fdReadMap, (fd_set *) NULL, (fd_set *) NULL, pPollTime);    if (rval <= 0)      continue;    else if (FD_ISSET (nSocket, &fdReadMap))     {      struct sockaddr_in stLastPacketFrom;      rval = recvfrom (nSocket, pPacket, nPacketSize, 0, (struct sockaddr *)&stLastPacketFrom, &nFromLength);      WSACleanup ();    }


To answer your question, I normally use a structure to send the data, not a simple string. The problem is there in both version. The string is there only because I wanted to remove as many things as possible to identify the source of the problem.

Antheus, it's a good information you gave me. Unfortunately, it does the same thing when I fix it using a int.
That's interesting. Following Oliii's post, I tried the same project on my old computer. And guess what... I don't have the problem. What's funny is studio loads a bunch of extra dll on the computer that causes errors... Here are the extra dlls, don't know what they are for.

'comm2.exe': Loaded 'D:\WINDOWS\system32\secur32.dll'
'comm2.exe': Loaded 'D:\WINDOWS\WinSxS\x86_Microsoft.VC90.DebugCRT_1fc8b3b9a1e18e3b_9.0.21022.8_x-ww_597c3456\msvcr90d.dll'
'comm2.exe': Loaded 'D:\WINDOWS\system32\nvappfilter.dll', Binary was not built with debug information.
'comm2.exe': Loaded 'D:\WINDOWS\system32\ole32.dll'
'comm2.exe': Loaded 'D:\WINDOWS\system32\psapi.dll'
'comm2.exe': Loaded 'D:\WINDOWS\system32\oleaut32.dll'
'comm2.exe': Loaded 'D:\WINDOWS\system32\wshtcpip.dll'
'comm2.exe': Loaded 'D:\WINDOWS\system32\uxtheme.dll'
'comm2.exe': Loaded 'D:\WINDOWS\system32\msctf.dll'
'comm2.exe': Loaded 'D:\WINDOWS\system32\clbcatq.dll'
'comm2.exe': Loaded 'D:\WINDOWS\system32\comres.dll'
'comm2.exe': Loaded 'D:\WINDOWS\system32\version.dll'
'comm2.exe': Loaded 'D:\WINDOWS\system32\xpsp2res.dll', Binary was not built with debug information.
'comm2.exe': Loaded 'D:\WINDOWS\system32\sxs.dll'

This topic is closed to new replies.

Advertisement