472,371 Members | 1,375 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 472,371 software developers and data experts.

BUG in System.Drawing.Font!

I'm using the .NET Memory Profiler by Sci Tech and I wrote a little
test application to verify something odd I observed and it appears
that System.Drawing.Font fails to dispose of its FontFamily.

I run the following code:

// BEGIN
while( true )
{
System.Drawing.Graphics dc=lblClock.CreateGraphics();
dc.Clear(Color.White);
Font f=new Font("Arial", 10, FontStyle.Bold);
dc.DrawString(DateTime.Now.ToString("yyyy MMM dd, hh:mm:ss",
ClockDTFI), f, Brushes.Black, 5, 0);
f.Dispose();
dc.Dispose();
}
// END

This is just to see if I can generate lots of fonts, dispose of them,
and verify that they are disposing of their unmanaged resources, but
the .NET Memory Profiler shows that there are *thousands* of
FontFamily objects that haven't been disposed.

I am not certain but I suspect this is causing a memory leak because
my program's memory grows and grows.

Even if I call f.FontFamily.Dispose() it still says there are
thousands of FontFamily objects that haven't been disposed.
Jul 21 '05 #1
3 7031
ba******@yahoo.com (Barry Anderberg) wrote in
news:9d**************************@posting.google.c om:
I'm using the .NET Memory Profiler by Sci Tech and I wrote a
little test application to verify something odd I observed and
it appears that System.Drawing.Font fails to dispose of its
FontFamily.

I run the following code:

// BEGIN
while( true )
{
System.Drawing.Graphics dc=lblClock.CreateGraphics();
dc.Clear(Color.White);
Font f=new Font("Arial", 10, FontStyle.Bold);
dc.DrawString(DateTime.Now.ToString("yyyy MMM dd, hh:mm:ss",
ClockDTFI), f, Brushes.Black, 5, 0);
f.Dispose();
dc.Dispose();
}
// END

This is just to see if I can generate lots of fonts, dispose of
them, and verify that they are disposing of their unmanaged
resources, but the .NET Memory Profiler shows that there are
*thousands* of FontFamily objects that haven't been disposed.

I am not certain but I suspect this is causing a memory leak
because my program's memory grows and grows.

Even if I call f.FontFamily.Dispose() it still says there are
thousands of FontFamily objects that haven't been disposed.


Barry,

It's not a memory leak. Unmanaged resources and memory are two
different things. The calls to IDisposable.Dispose are properly
freeing the unmanaged resources (i.e. the low level font handles).
Otherwise, you would be getting some kind of exception about no
available handles.

The memory used by the Graphics and Font instances is managed by the
Garbage Collector (GC). It simply hasn't gotten around to reclaiming
the memory used by those objects. If you're an experienced C, C++ or
Delphi developer, it may be hard to ignore the growing memory usage,
but that's usually the best thing to do. The GC is a very well
written piece of software. Trust it to do its job.

MSDN has several good articles explaining how the GC works:
http://msdn.microsoft.com/msdnmag/is...00/GCI/TOC.ASP

http://msdn.microsoft.com/msdnmag/is...0/GCI2/TOC.ASP

http://msdn.microsoft.com/library/en-
us/dndotnet/html/dotnetgcbasics.asp

(TinyURL: http://tinyurl.com/2tzpn)

http://msdn.microsoft.com/library/en-
us/dndotnet/html/dotnetperftechs.asp

(TinyURL: http://tinyurl.com/3890)
Hope this helps.

Chris.
-------------
C.R. Timmons Consulting, Inc.
http://www.crtimmonsinc.com/
Jul 21 '05 #2
Chris,

I am not sure I agree with you. I am familiar with the GC and how/when
it collects garbage. It collects once the managed heap is full, and at
some other times. So I wrote the test application to deliberately fill
the heap to force a garbage collection. I also added a button to the
form to call GC.Collect() and according to the memory profiler, these
objects have not been disposed. I realize that they have been garbage
collected, but that does not mean there are no leaks. If unmanaged
resources are not freed, the garbage collector will not do it for you.
The unmanaged resources are freed by the underlying framework code when
the object is disposed, or in the finalize method of the class in
question. The only thing I can assume is that the finalize method is
doing the job, but I still think it's a bug in the framework that the
Dispose method of the Font's objects aren't being called. Any class
that implements IDisposable should have its dispose method called. The
finalize method is a last resort when the programmer does not call
Dispose like he should. Isn't that your understanding as well?

Again, you're probably right that there's no leak but it makes for
considerable confusion when running a memory profiler that tracks
undisposed objects. We have a major piece of software at my job and it
is slowly eating up the memory and eating up the entire pagefile causing
major fragmentation of the pagefile, ultimately slowing down the system
and causing other remoted applications to begin timing out. I've been
spending lots of time pouring over code and running this memory profiler
and I'm at a loss as to why this is happening. The FontFamily class is
only one of many objects that the .NET framework is not disposing of
even though the classes implement IDisposable. That's simply bad
programming on the part of Microsoft. One thing to note is that we're
using the 1.0 Framework which may explain these issues. Perhaps the
objects are being properly disposed of in the newer .NET Framework.

Thanks for the reply,

Barry

*** Sent via Developersdex http://www.developersdex.com ***
Don't just participate in USENET...get rewarded for it!
Jul 21 '05 #3
Barry Anderberg <ba******@yahoo.com> wrote in
news:#9**************@TK2MSFTNGP11.phx.gbl:
Chris,

I am not sure I agree with you. I am familiar with the GC and
how/when it collects garbage. It collects once the managed heap
is full, and at some other times. So I wrote the test
application to deliberately fill the heap to force a garbage
collection. I also added a button to the form to call
GC.Collect() and according to the memory profiler, these objects
have not been disposed. I realize that they have been garbage
collected, but that does not mean there are no leaks. If
unmanaged resources are not freed, the garbage collector will
not do it for you. The unmanaged resources are freed by the
underlying framework code when the object is disposed, or in the
finalize method of the class in question. The only thing I can
assume is that the finalize method is doing the job, but I still
think it's a bug in the framework that the Dispose method of the
Font's objects aren't being called. Any class that implements
IDisposable should have its dispose method called. The finalize
method is a last resort when the programmer does not call
Dispose like he should. Isn't that your understanding as well?

Again, you're probably right that there's no leak but it makes
for considerable confusion when running a memory profiler that
tracks undisposed objects. We have a major piece of software at
my job and it is slowly eating up the memory and eating up the
entire pagefile causing major fragmentation of the pagefile,
ultimately slowing down the system and causing other remoted
applications to begin timing out. I've been spending lots of
time pouring over code and running this memory profiler and I'm
at a loss as to why this is happening. The FontFamily class is
only one of many objects that the .NET framework is not
disposing of even though the classes implement IDisposable.
That's simply bad programming on the part of Microsoft. One
thing to note is that we're using the 1.0 Framework which may
explain these issues. Perhaps the objects are being properly
disposed of in the newer .NET Framework.


Barry,

I think I duplicated your bug in .Net 1.1.

Depending upon the Font constructor used, each instance of the Font
class creates one or two instances of the FontFamily class for its
own internal use, but never disposes of them.

This code results in two FontFamily instances being created (and not
disposed of):

Font f = new Font("Arial", 10, FontStyle.Bold);
...
f.Dispose();

Whereas passing an existing instance of FontFamily to the Font
constructor only results in one undisposed instance of FontFamily:

FontFamily fontFamily = new FontFamily("Arial");
Font f = new Font(fontFamily, 10, FontStyle.Bold);
...
f.Dispose();
fontFamily.Dispose();

If you want to dig into the .Net framework source code, there is a
great utility called Reflector available at:

http://www.aisto.com/roeder/dotnet/

With it, you can view the decompiled C# source of all of the methods
of the Font and FontFamily classes (and all the rest of the .Net
framework.)

At this point, about the only constructive advice I can offer is the
obvious: minimize the number of instances that don't get properly
disposed. Something like creating a handful of global Font instances
and re-using them throughout the app.

FWIW, here's a short program that demonstrates the problem:

// Compile with "csc /t:exe example.cs"

using System;
using System.Drawing;
using System.Windows.Forms;

namespace TestNamespace
{
public class TestClass
{
[STAThread]
public static void Main()
{
using (Label lblClock = new Label())
{
using (Graphics dc = lblClock.CreateGraphics())
{

// The Font instances get disposed of OK, but
// there will be 2000 undisposed instances of
// FontFamily.

for (int i = 0; i < 1000; i++)
{
dc.Clear(Color.White);
using (Font f = new Font("Arial", 10, FontStyle.Bold))
{
dc.DrawString(DateTime.Now.ToString(
"yyyy MMM dd, hh:mm:ss"), f, Brushes.Black, 5, 0);
}
}
}
}

Console.WriteLine("Done.");
Console.ReadLine();
}
}
}
Chris.
-------------
C.R. Timmons Consulting, Inc.
http://www.crtimmonsinc.com/
Jul 21 '05 #4

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

1
by: | last post by:
Hello, I am learning how to use the XmlSerializer. I have a class that has a member of type System.Drawing.Font such as: public class MyClass { Font font;
1
by: Paul Hoad | last post by:
I'm trying to use MeasureString() to determine the length in pixels of a string However to do I need a System.Drawing.Graphics object to do this I need to create a System.Drawing.Graphics...
3
by: Barry Anderberg | last post by:
I'm using the .NET Memory Profiler by Sci Tech and I wrote a little test application to verify something odd I observed and it appears that System.Drawing.Font fails to dispose of its FontFamily. ...
2
by: Kyjan | last post by:
Greetings to all! I was wondering if anyone had ever seen this error before: Exception message: Invalid parameter used. (source='System.Drawing', method='GetHeight') Portion of the stack...
4
by: Liverpool fan | last post by:
I have a windows application written using VB .NET that encompasses a countdown timer modal dialog. The timer is a System.Timers.Timer with an interval of 1 second. AutoReset is not set so accepts...
1
by: Martijn Mulder | last post by:
At startup my application loads an image from a file from disk. If the file is not there, I still need a valid System.Drawing.Image object but I don't know how to get one. //class MyImage...
3
by: forest demon | last post by:
for example, let's say I do something like, System.Diagnostics.Process.Start("notepad.exe","sample.txt"); if the user does a SaveAs (in notepad), how can i capture the path that the user...
2
by: =?Utf-8?B?TmF0aGFuIFdpZWdtYW4=?= | last post by:
Hi, I am wondering why the .NET Framework is quite different from Win32 API when it comes to displaying system modal message boxes. Consider the four following types of system modal message...
2
by: ThatsIT.net.au | last post by:
I have this code that writes a pie chart in a asp.net page, but I want to use it in a server control. When I try I get a error on the last line "Response.OutputStream" Obviously there is no...
2
by: Kemmylinns12 | last post by:
Blockchain technology has emerged as a transformative force in the business world, offering unprecedented opportunities for innovation and efficiency. While initially associated with cryptocurrencies...
0
by: Naresh1 | last post by:
What is WebLogic Admin Training? WebLogic Admin Training is a specialized program designed to equip individuals with the skills and knowledge required to effectively administer and manage Oracle...
0
by: antdb | last post by:
Ⅰ. Advantage of AntDB: hyper-convergence + streaming processing engine In the overall architecture, a new "hyper-convergence" concept was proposed, which integrated multiple engines and...
1
by: Matthew3360 | last post by:
Hi, I have been trying to connect to a local host using php curl. But I am finding it hard to do this. I am doing the curl get request from my web server and have made sure to enable curl. I get a...
0
Oralloy
by: Oralloy | last post by:
Hello Folks, I am trying to hook up a CPU which I designed using SystemC to I/O pins on an FPGA. My problem (spelled failure) is with the synthesis of my design into a bitstream, not the C++...
0
by: Carina712 | last post by:
Setting background colors for Excel documents can help to improve the visual appeal of the document and make it easier to read and understand. Background colors can be used to highlight important...
0
BLUEPANDA
by: BLUEPANDA | last post by:
At BluePanda Dev, we're passionate about building high-quality software and sharing our knowledge with the community. That's why we've created a SaaS starter kit that's not only easy to use but also...
2
by: Ricardo de Mila | last post by:
Dear people, good afternoon... I have a form in msAccess with lots of controls and a specific routine must be triggered if the mouse_down event happens in any control. Than I need to discover what...
0
by: jack2019x | last post by:
hello, Is there code or static lib for hook swapchain present? I wanna hook dxgi swapchain present for dx11 and dx9.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.