Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

HELP!! CSocket and CAsyncSocket Consumes Memory Uncontrollably

104 views
Skip to first unread message

Roger Garrett

unread,
Aug 23, 2005, 1:22:03 PM8/23/05
to
HELP !!!

I've written a server and client program using CSockets.

My programs work quite well. But they continually consume more and more
memory until the whole thing crashes. If I stop it at some point (while
debugging with the VS IDE) and return to the IDE, it never reports any memory
leaks. Yet, when I run the program and watch the memory usage of the
application via the Windows Task Manager I can see its memory usage going up
and up and up endlessly.

I did some tests that are basically:

int n;
for (n = 0 ; n < 10000 ; +=n)
{
CSocket* pSocket = (CSocket*) new CSocket;
pSocket->Create(0);
pSocket->Detach();
pSocket->Close();
delete pSocket;
}

That is, it merely allocates a CSocket and then deletes it.
Wnen I go through this loop I can watch the memory usage go up and up.
Clearly, the delete of the CSocket is not entirely deleting everything.

SAME PROBLEM WITH CAsyncSocket

I also tried the very same kind of thing with CAsyncSocket and I get the
very same symptoms, of memory constantly increasing for the app.

Is there a solution to the problem of not fully deleting CSockets or
CAsyncSockets?

I really need some help on this.

Eugene Gershnik

unread,
Aug 23, 2005, 8:40:48 PM8/23/05
to
Roger Garrett wrote:

> pSocket->Detach();

This most likely detaches a C++ CSocket object from OS SOCKET. (I don't know
what exactly CSocket does but this is the usual MFC naming convention)

> pSocket->Close();

This is probably no-op as there is no SOCKET to close in CSocket anymore

> delete pSocket;

And this destroys C++ object while the OS SOCKETS continues to live ;-)

If I am right it gives another reason why MFC's use of double-state
anti-pattern is a huge mistake.

--
Eugene
http://www.gershnik.com

Arkady Frenkel

unread,
Aug 24, 2005, 3:46:12 AM8/24/05
to
That's the reason: don't do detach if you didn't to attach() before and
don't do close too , just new / Create / delete.
You need attach/detach in multithreading only
Arkady

"Eugene Gershnik" <gers...@hotmail.com> wrote in message
news:exYM6REq...@TK2MSFTNGP10.phx.gbl...

Arkady Frenkel

unread,
Aug 24, 2005, 4:01:30 AM8/24/05
to
Eugene!
Just demystifying CSocket attach :) member : it create socket and window
for notifications and put both ( window and socket ) handles in it's
internal map
Arkady

"Eugene Gershnik" <gers...@hotmail.com> wrote in message
news:exYM6REq...@TK2MSFTNGP10.phx.gbl...

Roger Garrett

unread,
Aug 24, 2005, 11:13:10 AM8/24/05
to
IT'S WINDOWS VERSION SENSITIVE !

I did some extensive testing of this socket create/delete problem. It turns
out that it is sensitive to which version of Windows it is run under.

I wrote a really simple MFC dialog-based app that basically has a button
which, when clicked, does a large number of CAsyncSocket creations and
deletions.

The loop looks like this:

for (n = 0 ; n < nCount ; ++n)
{
CAsyncSocket* pSocket = new CAsyncSocket;
if (!pSocket->Create(0))
{
MessageBox("CAsyncSocket::Create failure","Socket problem");
}
delete pSocket;
}


By watching the Windows Task Manager I can see that the size of the
application increases as the sockets are created/deleted. Doing 10,000 socket
create/deletes causes the app to increase in size by over 12Mb. That is, that
happens when I run the app under Windows XP Home Edition. If I run it under
Windows 2000 there is no memory problem.

Does Microsoft know about this? Is there some way that I can notify them of
this situation?

Alexander Nickolov

unread,
Aug 24, 2005, 12:36:49 PM8/24/05
to
Which part of "you have a resource leak" do you have trouble
understanding?

--
=====================================
Alexander Nickolov
Microsoft MVP [VC], MCSD
email: agnic...@mvps.org
MVP VC FAQ: http://www.mvps.org/vcfaq
=====================================

"Roger Garrett" <RogerG...@discussions.microsoft.com> wrote in message
news:58AC90AA-21A8-4A7A...@microsoft.com...

Roger Garrett

unread,
Aug 24, 2005, 1:04:04 PM8/24/05
to
"Alexander Nickolov" wrote:

> Which part of "you have a resource leak" do you have trouble
> understanding?
>

Well, that's an incredibly rude statement to make.

"I" do not have a resource leak, Microsoft does.

I have spent considerable time and effort (and two other individuals within
this forum have also provided advice and help) isolating the problem and it
clearly occurs within the CAsyncSocket; in particular in the deletion of
CAsyncSocket objects when running under Windows XP Home Edition. Something is
allocated by the CAsyncSocket's Create() method which is never reclaimed when
the object is deleted (either explicitly or by going out of scope).

Just telling me that it's a resource leak and implying that it's something
that I have failed to handle does not address the issue. I have no control
over what CAsyncSocket does when it's supposed to be cleaning up after
itself. That's Microsoft's responsibility.

How utterly rude!

Alexander Nickolov

unread,
Aug 24, 2005, 1:12:05 PM8/24/05
to
Did you even read your replies? They clearly state you are leaking
socket handles, but why take responsibility when you can blame
all mistakes on Microsoft... As for your attitude - I'm speechless...

--
=====================================
Alexander Nickolov
Microsoft MVP [VC], MCSD
email: agnic...@mvps.org
MVP VC FAQ: http://www.mvps.org/vcfaq
=====================================

"Roger Garrett" <RogerG...@discussions.microsoft.com> wrote in message

news:BF3962C9-F29B-456C...@microsoft.com...

Phil Frisbie, Jr.

unread,
Aug 24, 2005, 2:44:26 PM8/24/05
to
Alexander Nickolov wrote:

> Did you even read your replies? They clearly state you are leaking
> socket handles, but why take responsibility when you can blame
> all mistakes on Microsoft... As for your attitude - I'm speechless...

He is still ticked off because he committed himself to using CSockets BEFORE he
found out what a poor wrapper they are......

--
Phil Frisbie, Jr.
Hawk Software
http://www.hawksoft.com

Eugene Gershnik

unread,
Aug 24, 2005, 2:40:57 PM8/24/05
to
Arkady Frenkel wrote:
> That's the reason: don't do detach if you didn't to attach() before
> and don't do close too , just new / Create / delete.
> You need attach/detach in multithreading only

Or if you got the SOCKET from sowehere not under MFC control. The point is
the whole Attach/Detach thing as well as Create/Close is useless junk. There
is a well defined mechanism in C++ to deal with acquisition/release and it
is constructors/destructors.


--
Eugene
http://www.gershnik.com

Roger Garrett

unread,
Aug 24, 2005, 5:09:03 PM8/24/05
to
If you will look at the subsequent code that I posted, namely:

for (n = 0 ; n < nCount ; ++n)
{
CAsyncSocket* pSocket = new CAsyncSocket;
if (!pSocket->Create(0))
{
MessageBox("CAsyncSocket::Create failure","Socket problem");
}
delete pSocket;
}

you will see that I removed the Detach() and Close() calls, thereby
stripping it down to its barest minimum. And that new code also exhibits the
problem of non-reclaimed memory. My understanding is that Close is
automatically called at the CAsyncSocket destructor and that the Close takes
care of the handle (and whatever's attached to that handle). So the above
code SHOULD work just fine and not exhibit any memory problems. But indeed it
does. Going through the above loop 10,000 times results in an additional 12Mb
for the running application size. And it doesn't go away.

Subsequent testing has shown that the problem exists on Windows XP Home
Edition but not on Windows 2000. In addition, if I get rid of the MFC class
altogether, by not using CAsyncSocket, but rather use the following:

for (n = 0 ; n < nCount ; ++n)
{

SOCKET s;
s = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
if ( s == INVALID_SOCKET )
{
MessageBox("Create failure","Socket problem");
}
shutdown( s, SD_BOTH );
closesocket( s );
}

then there is no memory problem.

The conclusion would seem to be that there is a problem with the
CAsyncSocket class when running under Windows XP and it is not a matter of
leaking socket handles.

May I suggest that someone else give this code a try and see if they can
duplicate my findings?

Eugene Gershnik

unread,
Aug 24, 2005, 6:51:33 PM8/24/05
to
Roger Garrett wrote:
> If you will look at the subsequent code that I posted, namely:
>
> for (n = 0 ; n < nCount ; ++n)
> {
> CAsyncSocket* pSocket = new CAsyncSocket;
> if (!pSocket->Create(0))
> {
> MessageBox("CAsyncSocket::Create failure","Socket
> problem"); }
> delete pSocket;
> }

[...]

> Subsequent testing has shown that the problem exists on Windows XP
> Home Edition but not on Windows 2000. In addition, if I get rid of
> the MFC class altogether, by not using CAsyncSocket, but rather use
> the following:
>
> for (n = 0 ; n < nCount ; ++n)
> {
> SOCKET s;
> s = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );
> if ( s == INVALID_SOCKET )
> {
> MessageBox("Create failure","Socket problem");
> }
> shutdown( s, SD_BOTH );
> closesocket( s );
> }
>
> then there is no memory problem.

You didn't mention (or I missed it) what version of MFC you are using. Is it
MFC 4.2, 7.0 or 7.1? The implementation could have changed between them.
Looking at MFC 7.1 sources your plain API code is not exactly equivalent.
Assuming the problem exist and it doesn't happen with plain API use it could
be a bug in MFC or your use of MFC. You can try to step into the MFC code in
debugger and see what exactly it is doing and where does it allocate memory.

> May I suggest that someone else give this code a try and see if they
> can duplicate my findings?

Could be tricky as I guess not many regulars here have access to XP Home.


--
Eugene
http://www.gershnik.com

Arkady Frenkel

unread,
Aug 25, 2005, 5:23:13 AM8/25/05
to

"Eugene Gershnik" <gers...@hotmail.com> wrote in message
news:O9Qfi0Nq...@tk2msftngp13.phx.gbl...

> Arkady Frenkel wrote:
>> That's the reason: don't do detach if you didn't to attach() before
>> and don't do close too , just new / Create / delete.
>> You need attach/detach in multithreading only
>
> Or if you got the SOCKET from sowehere not under MFC control.

That's exactly the point in multithreading that thread have to receive
native socket and not class
Arkady

Arkady Frenkel

unread,
Aug 25, 2005, 5:25:53 AM8/25/05
to
That's the only way , to go itno and check what happen in
destructor. BTW maybe that only problem with presentation in Home Edition.

Arkady
"Eugene Gershnik" <gers...@hotmail.com> wrote in message
news:er%23Pk5Pq...@TK2MSFTNGP15.phx.gbl...

Roger Garrett

unread,
Aug 25, 2005, 9:39:03 AM8/25/05
to
"Eugene Gershnik" wrote:

> You didn't mention (or I missed it) what version of MFC you are using. Is it
> MFC 4.2, 7.0 or 7.1? The implementation could have changed between them.
> Looking at MFC 7.1 sources your plain API code is not exactly equivalent.
> Assuming the problem exist and it doesn't happen with plain API use it could
> be a bug in MFC or your use of MFC.

I'm developing with Microsoft Development Environment 2002 Version 7.0.995.

The afxsock.h file shows Copyright (C) 1992-2001.

Does that tell you anything useful?

- Roger

Mike

unread,
Aug 25, 2005, 11:23:02 AM8/25/05
to
I've verified Roger's claims using Visual C++ 6.0 and MFC 4.2 on a Windows XP
Pro system. Stepping through the debugger did not make it immediately clear
to me where the problem was (the destructor does call Close, which calls
Detach, which destroys and deletes the underlying CWnd that CAsyncSocket
uses) and BoundsChecker claims that all resources were freed at program exit.

If I have time I'll check it out further but the other posters are correct
in that the MFC socket wrappers have a lot of unnecessary complexity. You'll
be much happier in the log run if you just rewrite your application to use
the Winsock API.

Mike

Eugene Gershnik

unread,
Aug 25, 2005, 12:57:04 PM8/25/05
to


Yes, it means that you use MFC 7.0 which I no longer have.
First advice: upgrade to VC 7.1 (a.k.a .NET 2003). The 7.0 you use is buggy
poor excuse for software release that MS should be ashamed of. I beleive the
upgrade is quite cheap (at least it used to be).
Second advice: consider dropping MFC sockets and using either direct API
calls or your own wrappers. The MFC [sockets] are poorly designed and don't
buy you anything IMHO.
Third advice: if you still want to get to bottom of this issue first you
need to establish whether the leak is a resource (possibly socket) one or a
plain memory leak. Download Process Explorer from SysInternal. This is one
must-have tool that any developer should have in any case. Check the number
of open handles for your process before you enter the loop, after one
iteration and after the loop finishes. If you see handle count grow you have
a resource leak and you will even find what kind of handle it is. Then the
only thing left is to find what leaks the handle in MFC code.
To check for memory leak first read this
http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsdebug/html/vxcondetectingisolatingmemoryleaks.asp
Create a check point just before you enter the loop and after the loop and
see if some memory is not freed.


--
Eugene
http://www.gershnik.com


Roger Garrett

unread,
Aug 26, 2005, 11:02:09 AM8/26/05
to
Eugene,

Thank you for the advice.

I had previously used CMemoryState to do some basic checking and that showed
no leaks (of the new-delete kind).

While running my tests the Windows Task Manager does indeed show that the
number of "handles" continuously grows as it iterates through the test loop.
I guess I'll have to take a look at the Process Explorer that you
recommended. Although even if I determine where the leak is coming from it's
not clear that I'll be able to do anything about it.

It may be that I'll just have to avoid Windows XP for this part of my app.
Unfortunately, my developer station is XP, so it makes debugging a bit of a
problem.


- Roger

0 new messages