Visual Studio
02 / 04

Debugging & Diagnostics

Visual Studio Debugging & Diagnostics

Visual Studio has the most powerful .NET debugger available. Conditional breakpoints, Edit and Continue, the Diagnostic Tools window, and IntelliTrace collectively cover debugging, profiling, and historical tracing — all from a single IDE.

Breakpoints

# Basic breakpoints
F9              # Toggle breakpoint on current line
F5              # Start debugging
Shift+F5        # Stop debugging
Ctrl+Shift+F5   # Restart debugging
F10             # Step Over (execute line, do not enter method)
F11             # Step Into (enter method)
Shift+F11       # Step Out (finish current method, return to caller)
F5              # Continue (run to next breakpoint)
Ctrl+F10        # Run to Cursor (temporary breakpoint at cursor position)
Shift+F9        # Quick Watch — evaluate expression while debugging

# Advanced breakpoints — right-click breakpoint dot → Conditions
# Condition types:
# "Expression is true": break when orderId == 42
# "When changed":       break when variable value changes
# Hit Count:            break every Nth time (e.g. every 100th iteration)
# Filter:               break only for specific thread/machine/process

# Tracepoint (log message, do not stop execution) — right-click breakpoint → Actions
# Print to Output window: "Processing order {orderId} for user {user.Name}"
# {} inserts current value of expression — no recompile needed

# Breakpoints window — view and manage all breakpoints
# Debug → Windows → Breakpoints (Ctrl+Alt+B)
# Export/Import breakpoint sets (XML file) — useful for sharing debug sessions

# Data breakpoints — break when a memory address changes
# Requires .NET 5+ or Native code
# While paused, right-click variable in Autos/Locals → "Break When Value Changes"

# Function breakpoints — break when a method is entered by name (no source needed)
# Ctrl+Alt+B → New → enter "Namespace.Class.Method"
# Useful for debugging third-party code or IL-generated methods

Debug Windows & Edit and Continue

# Debug windows (Debug → Windows menu while debugging)
# Autos       — variables used in current and preceding statement (auto-selected)
# Locals      — all variables in current scope
# Watch 1-4   — pin any expression to watch its value; evaluates as you step
# Call Stack  — complete call chain; double-click to navigate to frame
# Immediate   — evaluate/execute any C# expression mid-debug
#               e.g. ? user.Email  or  user.Name = "Test Override"
# Output      — Debug.WriteLine() output, event log
# Threads     — all running threads; right-click to freeze/thaw individual threads
# Parallel Watch  — view same variable across all threads simultaneously
# Memory 1-4  — raw memory inspector
# Modules     — loaded assemblies, DLLs, their paths and versions

# Keyboard shortcuts for debug windows
Ctrl+Alt+A   # Immediate Window
Ctrl+Alt+C   # Call Stack
Ctrl+Alt+W,1 # Watch Window 1
Ctrl+Alt+V,A # Autos Window
Ctrl+Alt+V,L # Locals Window

# Edit and Continue — modify code while paused and continue without restart
# Enable: Tools → Options → Debugging → Enable Edit and Continue
# Limitations: cannot add new types, change method signatures, add fields
# Works for: changing method bodies, fixing typos, adjusting logic

# Set Next Statement — skip lines or re-execute code
# Right-click any line while paused → "Set Next Statement" (Ctrl+Shift+F10)
# The yellow arrow (current execution point) jumps to that line
# Useful for re-running a block of code after fixing a condition

Diagnostic Tools & Profiler

# Diagnostic Tools window (opens automatically when debugging in VS 2015+)
# Debug → Windows → Show Diagnostic Tools (Ctrl+Alt+F2)
# Panels:
# Events timeline  — GC collections, snapshots, exceptions, breakpoints as events
# CPU Usage graph  — real-time CPU %; click "Take Snapshot" to capture a call tree
# Memory Usage     — managed heap; click snapshot to diff allocations between snapshots

# CPU profiler — find hot paths without attaching debugger
# Debug → Performance Profiler → CPU Usage → Start
# Let app run, click "Stop Collection"
# Flame chart shows call tree with % inclusive/exclusive time

# Memory snapshot diffing:
# 1. Click snapshot at baseline
# 2. Perform action that may leak
# 3. Click another snapshot
# 4. Compare: click "# Objects" diff — shows types with the most new instances

# Exception Settings (Ctrl+Alt+E)
# Configure which exceptions break execution:
# "Break when thrown" (not just unhandled) — enable for debugging NullReferenceException
# Check: Common Language Runtime Exceptions → System.NullReferenceException
# Add specific exception types using the + button

# IntelliTrace (Enterprise edition only) — record and replay execution history
# Enable: Debug → Options → IntelliTrace → Enable IntelliTrace
# Records method calls, exceptions, and thread activity during debug session
# After stopping: Debug → IntelliTrace Events window shows timeline
# Double-click any event to restore historical state (inspect variables at any past point)
# "Historical Debugging" — step backward through recorded events

# Remote debugging — attach VS to a process on another machine
# Run msvsmon.exe on target machine (Visual Studio Remote Debugger)
# VS: Debug → Attach to Process → Connection Type = Remote (no authentication)
# Enter target machine hostname → select process → Attach

Keep your own version of these notes — editable, searchable, and organised by your stack.

Start free