Sign in to follow this  

udp error in VS2008

This topic is 3574 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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?


Share this post


Link to post
Share on other sites
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...

Share this post


Link to post
Share on other sites
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));


Share this post


Link to post
Share on other sites
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

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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'

Share this post


Link to post
Share on other sites
Quote:
Original post by vince35

'comm2.exe': Loaded 'D:\WINDOWS\system32\nvappfilter.dll', Binary was not built with debug information.


This would be my guess.

On the same note, version 2.x of NetLimiter breaks IOCP. It has a memory corruption heisenbug. The worst thing is, everything works well, and it crashes only randomly under heavy load. The MMO forums however are full of error reports from clients as well.

It shows as "nl_lsp.dll". Uninstalling Netlimiter completely is the only thing that help. This one has caused me quite a few frustrating hours.

Share this post


Link to post
Share on other sites
Antheus, I have to say you're great!

Sure enough, nvappfilter.dll was my problem. It's fine since I uninstalled the Forceware Network Access Manager.

So far I don't see any side effect, but is that NAM anyway? I can't really find a good answer on the web. Is it only a firewall or is there to it?

Thanks again.

Share this post


Link to post
Share on other sites
Quote:
Original post by vince35

So far I don't see any side effect, but is that NAM anyway? I can't really find a good answer on the web. Is it only a firewall or is there to it?


It's likely SPI.

It requires pretty extensive implementation, very tight interaction between application and network layer, so various race conditions or allocation functions can have far-reaching consequences.

Share this post


Link to post
Share on other sites

This topic is 3574 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this