Tracking down Strings

Use this forum for questions on how to use .NET Memory Profiler and how to analyse memory usage.
Post Reply
PK
Posts: 6
Joined: Mon Mar 21, 2005 2:13 pm

Tracking down Strings

Post by PK » Thu Nov 08, 2007 6:29 pm

I'm having a problem understanding what is happening with my program regarding string objects. The string values are not been released from the GC for the whole length of the program run.

I have string values being created in a Public Class that aids in starting my program. The Public Class is called from a module which is called from a forms load procedure. I start the public class with a AS NEW statement in the module. When the public class has completed it returns true if anything went ok. Now when viewing the string object type I can found the strings created in the public class just sitting there and never get cleared. What is the best way to track down what is keeping a hold on the strings?

On one of the Call Stacks I get the following

ClsStartUp.LoadSystems()
mod_Startup.Controller()
myProgram.MyProgram_Load(object, EventArgs)
Form.OnLoad(EventArgs)
Form.OnCreateControl()
Control.CreateControl(bool)
Control.CreateControl()
Control.WmShowWindow(Message&)
Control.WndProc(Message&)
ScrollableControl.WndProc(Message&)
ContainerControl.WndProc(Message&)
Form.WmShowWindow(Message&)
Form.WndProc(Message&)
Control.ControlNativeWindow.OnMessage(Message&)
Control.ControlNativeWindow.WndProc(Message&)
NativeWindow.Callback(IntPtr, int, IntPtr, IntPtr)
[Unmanaged to managed transition]
[Managed to unmanaged transition]
SafeNativeMethods.ShowWindow(HandleRef, int)
Control.SetVisibleCore(bool)
Form.SetVisibleCore(bool)
Control.set_Visible(bool)
Application.ThreadContext.RunMessageLoopInner(int, ApplicationContext)
Application.ThreadContext.RunMessageLoop(int, ApplicationContext)
Application.Run(ApplicationContext)
WindowsFormsApplicationBase.OnRun()
WindowsFormsApplicationBase.DoApplicationModel()
WindowsFormsApplicationBase.Run(string[])
MyApplication.Main(string[])


Is it that the myProgram.MyProgram_Load(object, EventArgs) is keeping a hold on the objects? MyProgram is the start form and the program will not end until this has been closed.

My program at the moment is showing over 6000 instances of the string type and I found it very difficult to track a specific string, I have to keep scrolling through the entire list until I can found what I'm looking for. Is there a easier way?

-Paul

Andreas Suurkuusk
Posts: 1029
Joined: Wed Mar 02, 2005 7:53 pm

Post by Andreas Suurkuusk » Sun Nov 11, 2007 8:45 pm

To find out what's holding on to your string you need to investigate the root paths of the string. I doubt that the myProgram.MyProgram_Load(object, EventArgs) method is holding on to any instances, since it is probably no longer executing. Only a method that is currently executing code (by itself or in any inner methods called from the method) can hold on to an instance.

In version 3.0, the only way to step through a set of instances is to use the dropdown list in the instance details view. This has been improved in the next version of the profiler (which will be released soon). In the new version it will be possible to select a set of instances and investigate them using navigation buttons in the instance details view.
Best regards,

Andreas Suurkuusk
SciTech Software AB

PK
Posts: 6
Joined: Mon Mar 21, 2005 2:13 pm

Post by PK » Wed Nov 14, 2007 9:51 am

I'm still having problems understand what is happening with some string objects :(

I have done the most simple program of two forms. Form1 opens Form2. A button_Click in Form2 has Dim strString as String = "DO SOMETHING". I click on the button, I then close Form2 I make sure that form2 is disposed from form1 where I opened it.

Now when I take a snapshot and look in Types, I select String and I still find a reference to the String created in Form2. The call Stack is

Control.OnClick(EventArgs)
Button.OnClick(EventArgs)
Button.OnMouseUp(MouseEventArgs)
Control.WmMouseUp(Message&, MouseButtons, int)
Control.WndProc(Message&)
ButtonBase.WndProc(Message&)
Button.WndProc(Message&)
Control.ControlNativeWindow.OnMessage(Message&)
Control.ControlNativeWindow.WndProc(Message&)
NativeWindow.Callback(IntPtr, int, IntPtr, IntPtr)
[Unmanaged to managed transition]
[Managed to unmanaged transition]
UnsafeNativeMethods.DispatchMessageW(NativeMethods.MSG&)
Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(int, int, int)
Application.ThreadContext.RunMessageLoopInner(int, ApplicationContext)
Application.ThreadContext.RunMessageLoop(int, ApplicationContext)
Application.RunDialog(Form)
Form.ShowDialog(IWin32Window)
Form1.btnOpenReport_Click(object, EventArgs)
Control.OnClick(EventArgs)
Button.OnClick(EventArgs)
Button.OnMouseUp(MouseEventArgs)
Control.WmMouseUp(Message&, MouseButtons, int)
Control.WndProc(Message&)
ButtonBase.WndProc(Message&)
Button.WndProc(Message&)
Control.ControlNativeWindow.OnMessage(Message&)
Control.ControlNativeWindow.WndProc(Message&)
NativeWindow.Callback(IntPtr, int, IntPtr, IntPtr)
[Unmanaged to managed transition]
[Managed to unmanaged transition]
UnsafeNativeMethods.DispatchMessageW(NativeMethods.MSG&)
Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(int, int, int)
Application.ThreadContext.RunMessageLoopInner(int, ApplicationContext)
Application.ThreadContext.RunMessageLoop(int, ApplicationContext)
Application.Run(Form)
Module1.Main()


What is keeping the String Objects alive? :lol: Could somebody please help me understand this by doing the same test program in VB.NET and viewing the results. Thank you for your time.

Kind Regards
-Paul

Andreas Suurkuusk
Posts: 1029
Joined: Wed Mar 02, 2005 7:53 pm

Post by Andreas Suurkuusk » Wed Nov 14, 2007 11:06 pm

Strings are a very common type in the .NET runtime, and several instances will be created by the runtime itself.

In your example you load the constant string "DO SOMETHING" to a local variable. When JITting the method, the runtime must create an instance of the "DO SOMETHING" string, since it's going to assign it to a variable. This instance is kept alive by the runtime itself, and will not be unloaded until the AppDomain exits. If it did unload the string, it would need to reload it from the assembly each time the method is executed, which would affect performance and make things more complicated.

This should be a minor problem, since this only occurs for constant strings in the assembly. A dynamically created string (e.g. new String( 'A', 10 )), will not be kept alive.
Best regards,

Andreas Suurkuusk
SciTech Software AB

Post Reply

Who is online

Users browsing this forum: No registered users and 13 guests