Turn Your Vehicle Into a Smart Earning Asset

While you’re not driving your car or bike, it can still be working for you. MOTOSHARE helps you earn passive income by connecting your vehicle with trusted renters in your city.

🚗 You set the rental price
🔐 Secure bookings with verified renters
📍 Track your vehicle with GPS integration
💰 Start earning within 48 hours

Join as a Partner Today

It’s simple, safe, and rewarding. Your vehicle. Your rules. Your earnings.

DOTNET: Understanding Memory leaks and Debugging using dotMemory

I’ll give you:

  1. One self-contained Program.cs you can drop into a new project
  2. How to run it from command line
  3. Step-by-step: how to use dotMemory to detect the leak
  4. How to read dotMemory results & locate the leak
  5. How to fix it (clean version of the code)

1️⃣ Create the demo app

dotnet new web -n MemoryLeakDemo
cd MemoryLeakDemo
Code language: JavaScript (javascript)

Now replace the entire Program.cs with this:

This is self-sufficient: one file, no extra classes, no extra projects.


2️⃣ Run the app (command line)

From the MemoryLeakDemo folder:

dotnet run

It will listen on something like:

  • http://localhost:5000
  • https://localhost:5001

(Use the HTTP one for simplicity: http://localhost:5000)


3️⃣ Generate the leak

In another terminal (or browser / Postman):

A. Start leaking memory

Run a loop (PowerShell):

1..50 | ForEach-Object {
    curl "http://localhost:5000/leak"
}
Code language: JavaScript (javascript)

Or Git Bash:

for i in {1..50}; do curl -s "http://localhost:5000/leak" > /dev/null; done
Code language: JavaScript (javascript)

Then check stats:

curl "http://localhost:5000/stats"
Code language: JavaScript (javascript)

You should see Total stored MB growing (e.g. 250 MB).

B. Compare with non-leaking allocations

1..50 | ForEach-Object {
    curl "http://localhost:5000/noleak"
}
curl "http://localhost:5000/gc"
curl "http://localhost:5000/stats"
Code language: JavaScript (javascript)
  • /noleak allocates memory but does not store it → GC can clean it.
  • /leak allocates memory and keeps it in a static list → cannot be GC’d.

4️⃣ Profile with dotMemory – step by step

Assuming you have dotMemory GUI (Rider/Standalone):

Step 1: Start the app

Make sure dotnet run for MemoryLeakDemo is running.

Step 2: Open dotMemory

  • Start dotMemory
  • Choose “Profile Running Process” (or similar wording)
  • Select the dotnet.exe / MemoryLeakDemo.dll process
  • Click Run / Attach

Step 3: Take a baseline snapshot

In dotMemory:

  • Click “Get Snapshot” (or “Get Snapshot #1”).
  • Name it “Baseline (before leak)”.

Step 4: Generate the leak

Back in terminal:

1..100 | ForEach-Object {
    curl "http://localhost:5000/leak"
}
curl "http://localhost:5000/stats"
Code language: JavaScript (javascript)

You should see big total MB stored.

Step 5: Take snapshot after leak

In dotMemory:

  • Click “Get Snapshot” again.
  • Name it “After leak (static list)”.

Step 6: Optionally, force GC and snapshot

Back in terminal:

curl "http://localhost:5000/gc"
curl "http://localhost:5000/stats"
Code language: JavaScript (javascript)

Then in dotMemory:

  • Take Snapshot #3: “After GC”.

5️⃣ Understanding dotMemory results (how to spot the leak)

Now the fun part: reading dotMemory.

A. Compare snapshots (Baseline vs After leak)

  1. In dotMemory, select “Baseline” and “After leak” snapshots.
  2. Click “Compare Snapshots”.

Look at:

  • Heap size increased a lot
  • New objects count is huge
  • Top types by size will likely show System.Byte[] (byte arrays)

B. Drill into byte[] and find retention

Click on System.Byte[] and open:

  • “Retention Graph”
  • or “Shortest Paths to GC Roots”

You should see a path like:

Static fieldLeakStore.BuffersList<byte[]> → byte[]
Code language: CSS (css)

This tells you:

  • The byte[] objects are alive because they are referenced by a static list.
  • That static list is LeakStore.Buffers.

This is your memory leak.

C. Check what happens after GC

Compare “After leak” vs “After GC” snapshots:

  • If byte[] objects are still around in large numbers/size → GC cannot free them.
  • Why? Because they’re still referenced by LeakStore.Buffers.

That is exactly how dotMemory exposes real leaks:

Objects survive GCs and are retained by long-lived references (statics, singletons, caches, events, etc.).


6️⃣ Common real-world patterns similar to this leak

  • Static lists/dictionaries that grow but never shrink
  • Caches without eviction policies
  • Event handlers where you forget to -= unsubscribe
  • Long-lived singletons holding request-scoped data
  • Task or Timer callbacks closing over large objects
  • In-memory queues that never get drained

dotMemory will show all of these as:

  • Big retained size
  • GC roots pointing to static fields, singletons, or event tables

7️⃣ How to fix this leak (clean code version)

Here’s a fixed version of the leak part:

Option A: Limit the cache

static class LeakStore
{
    private const int MaxBuffers = 10;
    private static readonly Queue<byte[]> Buffers = new();

    public static void AddBuffer(byte[] buffer)
    {
        Buffers.Enqueue(buffer);
        while (Buffers.Count > MaxBuffers)
        {
            Buffers.Dequeue(); // old buffers become eligible for GC
        }
    }

    public static int Count => Buffers.Count;
}
Code language: PHP (php)

Then in /leak:

var buffer = new byte[bytes];
// ...
LeakStore.AddBuffer(buffer);
Code language: JavaScript (javascript)

Now dotMemory will show:

  • Heap size not growing unbounded
  • Byte arrays being collected over time

Option B: Don’t use static leaks at all

  • Use scoped dependencies
  • Avoid unbounded global collections
  • Use proper cache with TTL / LRU (e.g., MemoryCache)

8️⃣ In-Code Metrics (like we did for TLS)

For this example, /stats already gives:

  • Number of stored buffers
  • Total MB stored
  • Number of leak calls

You can show this in the terminal while dotMemory shows heap graph growth → this connects code behavior + profiler view.


Subscribe
Notify of
guest
0 Comments
Newest
Oldest Most Voted
Inline Feedbacks
View all comments

Certification Courses

DevOpsSchool has introduced a series of professional certification courses designed to enhance your skills and expertise in cutting-edge technologies and methodologies. Whether you are aiming to excel in development, security, or operations, these certifications provide a comprehensive learning experience. Explore the following programs:

DevOps Certification, SRE Certification, and DevSecOps Certification by DevOpsSchool

Explore our DevOps Certification, SRE Certification, and DevSecOps Certification programs at DevOpsSchool. Gain the expertise needed to excel in your career with hands-on training and globally recognized certifications.

0
Would love your thoughts, please comment.x
()
x