This is a repost of my article, originally published on CodeProject on 24 May 2016.
The Story of a Memory Dump
Memory dumps are a common way to diagnose various problems with our applications (such as memory leaks or application hangs). You may think of them as photos which allow you to have a look at the past and notice all the details you might have missed. There are different types of memory dumps which we may compare to different types of photos we take:
- minimal – focus is on one element (such as an exception) and the whole background is blurry, they take very little space on the hardrive (eg. 2MB)
- minidumps with thread and process data/heaps/stacks/exception data, etc. – depending on how many options we choose, they might be very detailed high-resolution pictures or very blurry ones, the range of space they take can vary from tens of MBs to several GBs
- full memory dumps – those can be compared to high-resolution pictures, they are as big as the whole process committed virtual memory
Every developer knows that unit testing improves the quality of the code. We also profit from static code analysis and use tools such as SonarQube in our build pipelines. Yet, I still find that many developers are not aware of a much older way of checking the validity of the code: assertions. In this post, I will present you the benefits of using assertions, as well as some configuration tips for .NET applications. We will also learn how .NET and Windows support them.
I recently spent some time analyzing OutputDebugString method. For my another experiment I needed a version of OutputDebugString which depends only on Native API. While implementing it, I discovered few interesting facts about OutputDebugString that maybe will interest you too. The title mentions System.Diagnostics.Trace. It is because the default trace configuration in .NET sends trace messages to an instance of the DefaultTraceListener class, which uses OutputDebugString. And if you do not remove it explicitly from the trace listener collection, your logs will always go through it. You will later see why sometimes it might not be a good idea.
One of my colleagues at work was struggling with a peculiar problem on his machine. Whenever he tried to access the address of his test project: http://my.project:8080 he was getting connection refused error (my.project points to 127.0.0.1 in the hosts file). The same error appeared when we opened the http://127.0.0.1:8080 address:
Recently, the idea of protected variables in TFS struck my attention and pushed me to do some more research on how exactly those variables are stored. I hope I will write a separate post on that subject, but today I would like to share with you a small trick I use whenever I need to work with managed application traces (and TFS is one of them).
On Windows, when I want to know how things work internally, I usually start with procmon. Seeing which paths and registry keys are accessed, combined with TCP/IP connections is often enough to get an idea where to put breakpoints in further analysis. My TFS investigation was no exception to this rule. I collected a trace while saving a protected build variable – this is how such a variable looks like (in case you are interested :)):