🐛 Debug Configurations - AudioLab¶
Debugger launch configurations for AudioLab audio plugin development
📋 Table of Contents¶
- Overview
- Files in This Directory
- Available Configurations
- Debug Workflow
- DAW Integration
- Configuration Details
- Keyboard Shortcuts
- Platform-Specific Debugging
- Advanced Debugging
- Troubleshooting
Overview¶
Purpose: Debug AudioLab plugins in DAWs, standalone apps, and unit tests.
What are Launch Configurations? - Debugger setups for different scenarios - Specify executable, arguments, environment - Breakpoint support, variable inspection - Step-through debugging (F10, F11) - Watch expressions, call stack analysis
Use Cases: - Debug plugin loaded in Reaper/Logic/Ableton - Debug standalone application - Debug unit tests (Catch2) - Attach to running DAW process - Analyze crash dumps (core dumps)
Files in This Directory¶
launch.json¶
Primary debug configurations for AudioLab.
Content: - Plugin debugging: Reaper, Logic Pro, Ableton Live - Standalone debugging: Debug standalone app - Test debugging: Debug unit tests - Attach configurations: Attach to running process - Core dump analysis: Post-mortem debugging
Location: vscode/launch/launch.json
Used by: - Debug panel (Ctrl+Shift+D) - F5 key (start debugging) - Run and Debug view
Available Configurations¶
Select configuration from Debug panel dropdown (Ctrl+Shift+D).
Plugin Debugging¶
| Configuration | Platform | Description |
|---|---|---|
| Debug Plugin (Reaper) | Windows/Linux | Launch Reaper with plugin loaded |
| Debug Plugin (Reaper macOS) | macOS | Launch Reaper with plugin (macOS) |
| Debug Plugin (Logic Pro) | macOS | Launch Logic Pro with plugin |
| Debug Plugin (Ableton Live) | All | Launch Ableton Live with plugin |
| Debug Plugin (Standalone) | All | Debug standalone application |
Test Debugging¶
| Configuration | Platform | Description |
|---|---|---|
| Debug Unit Tests | All | Debug Catch2 test executable |
| Debug Audio Tests | All | Debug audio processing tests |
| Debug DSP Tests | All | Debug DSP algorithm tests |
| Debug Single Test | All | Debug specific test case |
Advanced Debugging¶
| Configuration | Platform | Description |
|---|---|---|
| Attach to Process | All | Attach to running DAW/app |
| Attach to Reaper | All | Quick attach to Reaper process |
| Debug Core Dump | Linux | Analyze crash dump file |
| Remote Debug (SSH) | Linux | Debug on remote machine |
Debug Workflow¶
Basic Workflow¶
1. Set Breakpoints
Method 1: Click left gutter (next to line number)
Method 2: Press F9 on line
Method 3: Right-click → Insert Breakpoint
Red dot appears = Breakpoint set
Hollow red circle = Breakpoint disabled
2. Select Debug Configuration
1. Open Debug panel: Ctrl+Shift+D (Cmd+Shift+D on macOS)
2. Select config from dropdown (top of panel)
Example: "Debug Plugin (Reaper)"
3. Config defines:
- Which executable to run (Reaper.exe)
- Arguments to pass
- Working directory
3. Start Debugging
Method 1: Press F5
Method 2: Click green play button (Debug panel)
Method 3: Menu: Run → Start Debugging
What happens:
- DAW launches (or app starts)
- Debugger attaches
- Execution pauses at breakpoints
4. Use Debug Controls
F5 - Continue (run until next breakpoint)
F10 - Step Over (execute line, don't enter functions)
F11 - Step Into (enter function calls)
Shift+F11 - Step Out (exit current function)
Shift+F5 - Stop debugging
Ctrl+Shift+F5 - Restart debugging
5. Inspect Variables
VARIABLES panel (left sidebar):
- Local variables
- Function arguments
- Global variables
Hover over variable in code:
- Shows current value
- Can expand objects/arrays
WATCH panel:
- Add custom expressions
- Example: "buffer.getNumSamples()"
6. View Call Stack
CALL STACK panel:
- Shows function call hierarchy
- Click frame to jump to that function
- Useful for understanding execution flow
Example:
processBlock() <-- Current
AudioProcessor::process()
VST3Wrapper::process()
ReaperHost::runAudio()
DAW Integration¶
Debugging in Reaper¶
Windows Configuration:
{
"name": "Debug Plugin (Reaper)",
"type": "cppdbg",
"request": "launch",
"program": "C:/Program Files/REAPER (x64)/reaper.exe",
"args": [],
"cwd": "${workspaceFolder}",
"environment": [],
"externalConsole": false,
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing for gdb",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "Build: Debug"
}
Workflow:
1. Build plugin: preLaunchTask runs "Build: Debug"
2. Plugin copied to Reaper VST3 folder (CMake post-build)
3. Reaper launches
4. Load plugin in Reaper track
5. Breakpoint hits when plugin processes audio
Tips:
- Create Reaper test project: test_projects/debug.rpp
- Pre-load plugin in project for faster workflow
- Use -audiocfg 0 to prevent audio device dialog
Debugging in Logic Pro (macOS)¶
macOS Configuration:
{
"name": "Debug Plugin (Logic Pro)",
"type": "lldb",
"request": "launch",
"program": "/Applications/Logic Pro X.app/Contents/MacOS/Logic Pro X",
"args": [],
"cwd": "${workspaceFolder}",
"preLaunchTask": "Build: Debug"
}
Workflow:
1. Build plugin (Universal Binary: x86_64 + arm64)
2. Plugin copied to ~/Library/Audio/Plug-Ins/VST3/
3. Logic launches
4. Create new track → Insert plugin
5. Breakpoint hits
Tips:
- Logic uses component validation: First load is slow
- Create template project with plugin pre-loaded
- Use Console.app to see plugin logs
Debugging in Ableton Live¶
Configuration:
{
"name": "Debug Plugin (Ableton Live)",
"type": "cppdbg",
"request": "launch",
"program": "C:/ProgramData/Ableton/Live 11 Suite/Program/Ableton Live 11 Suite.exe",
"args": [],
"cwd": "${workspaceFolder}",
"preLaunchTask": "Build: Debug"
}
macOS:
Workflow: 1. Build and copy plugin 2. Ableton launches 3. Create MIDI/Audio track 4. Drag plugin from browser 5. Debug as audio plays
Configuration Details¶
Anatomy of a Launch Configuration¶
{
"name": "Config Name", // Display name in dropdown
"type": "cppdbg", // Debugger type (cppdbg, lldb)
"request": "launch", // launch or attach
"program": "/path/to/exe", // Executable to run/attach
"args": ["--flag", "value"], // Command-line arguments
"cwd": "${workspaceFolder}", // Working directory
"environment": [ // Environment variables
{
"name": "MY_VAR",
"value": "my_value"
}
],
"preLaunchTask": "Build: Debug", // Task to run before launch
"postDebugTask": "Clean Up", // Task after debug session
"stopAtEntry": false, // Pause at main() entry
"externalConsole": false, // Use external console window
"MIMode": "gdb", // Debugger: gdb, lldb
"setupCommands": [ // Debugger init commands
{
"text": "-enable-pretty-printing"
}
]
}
Request Types¶
1. Launch (request: "launch")
- Purpose: Start new process
- Use Case: Launch DAW, standalone app, test executable
- Example: Launch Reaper with plugin
2. Attach (request: "attach")
- Purpose: Attach to running process
- Use Case: DAW already running, attach debugger
- Example: Attach to existing Reaper.exe
Attach Configuration:
{
"name": "Attach to Process",
"type": "cppdbg",
"request": "attach",
"processId": "${command:pickProcess}", // Prompts to select process
"MIMode": "gdb"
}
Workflow: 1. Start DAW manually 2. Load plugin 3. Run "Attach to Process" config 4. Select DAW process from list 5. Debugger attaches, breakpoints active
Debugger Types¶
Windows:
- cppdbg (Microsoft C++ debugger via GDB/LLDB)
- cppvsdbg (Visual Studio debugger, requires C/C++ extension)
macOS:
- lldb (LLDB debugger from Xcode)
- cppdbg (also works on macOS)
Linux:
- cppdbg (GDB debugger)
Choice: - cppdbg: Cross-platform, works on all OS - cppvsdbg: Windows-only, better integration with MSVC - lldb: macOS-specific, best for macOS development
Keyboard Shortcuts¶
Debug workflow shortcuts (see keybindings/README.md):
Windows/Linux¶
F5 - Start debugging / Continue
Shift+F5 - Stop debugging
Ctrl+Shift+F5 - Restart debugging
Ctrl+F5 - Run without debugging
F9 - Toggle breakpoint
F10 - Step over
F11 - Step into
Shift+F11 - Step out
Ctrl+Shift+D - Open Debug panel
macOS¶
F5 - Start debugging / Continue
Shift+F5 - Stop debugging
Cmd+Shift+F5 - Restart debugging
Cmd+F5 - Run without debugging
F9 - Toggle breakpoint
F10 - Step over
F11 - Step into
Shift+F11 - Step out
Cmd+Shift+D - Open Debug panel
Platform-Specific Debugging¶
Windows (MSVC)¶
Debugger: cppvsdbg (recommended) or cppdbg
Configuration:
{
"name": "Debug Plugin (Windows MSVC)",
"type": "cppvsdbg",
"request": "launch",
"program": "C:/Program Files/REAPER (x64)/reaper.exe",
"args": [],
"cwd": "${workspaceFolder}",
"symbolSearchPath": "${workspaceFolder}/build/Debug",
"externalConsole": false,
"logging": {
"moduleLoad": false,
"trace": false
}
}
Features: - Native Windows debugging - Better symbol resolution - Faster than GDB on Windows - Edit and Continue (some cases)
Requirements: - C/C++ Extension Pack installed - MSVC compiler (cl.exe) - .pdb debug symbols
macOS (LLDB)¶
Debugger: lldb
Configuration:
{
"name": "Debug Plugin (macOS)",
"type": "lldb",
"request": "launch",
"program": "/Applications/Reaper.app/Contents/MacOS/REAPER",
"args": [],
"cwd": "${workspaceFolder}",
"preLaunchTask": "Build: Debug"
}
Features: - Native macOS debugging - dSYM symbol support - Objective-C++ support - Apple Silicon (arm64) support
Tips:
- Generate dSYM: -g -gdwarf-2 in CMake
- Code signing: Debug builds auto-signed
- Sandbox: May need entitlements for DAW debugging
Linux (GDB)¶
Debugger: cppdbg (uses GDB)
Configuration:
{
"name": "Debug Plugin (Linux)",
"type": "cppdbg",
"request": "launch",
"program": "/usr/bin/reaper",
"args": [],
"cwd": "${workspaceFolder}",
"MIMode": "gdb",
"setupCommands": [
{
"description": "Enable pretty-printing",
"text": "-enable-pretty-printing",
"ignoreFailures": true
}
],
"preLaunchTask": "Build: Debug"
}
Tips:
- Install GDB: sudo apt install gdb
- Disable ASLR: setarch $(uname -m) -R gdb
- Core dumps: ulimit -c unlimited
Advanced Debugging¶
Conditional Breakpoints¶
Set condition on breakpoint:
1. Set breakpoint (F9)
2. Right-click red dot → Edit Breakpoint
3. Enter condition:
Examples:
- sampleIndex == 1024
- buffer.getNumSamples() > 0
- parameterValue < 0.0f
4. Breakpoint only hits when condition true
Use Case: Debug specific audio buffer frame without stopping on every call.
Logpoints (Non-Breaking Breakpoints)¶
Print message without stopping:
1. Right-click line → Add Logpoint
2. Enter message: "Sample value: {sampleValue}"
3. Logpoint prints to Debug Console
4. Execution continues (no pause)
Example:
// Logpoint at line 42:
// Message: "Processing buffer: {buffer.getNumSamples()} samples"
void processBlock(AudioBuffer<float>& buffer)
{
// Logpoint here prints: "Processing buffer: 512 samples"
for (int i = 0; i < buffer.getNumSamples(); ++i)
{
// ...
}
}
Watch Expressions¶
Monitor custom expressions:
1. Open WATCH panel (Debug sidebar)
2. Click + to add expression
3. Enter expression:
Examples:
- buffer.getWritePointer(0)[0]
- std::sqrt(paramValue * 2.0f)
- myVector.size()
4. Expression updates as you step through code
Use Case: Monitor complex calculations, vector sizes, buffer contents.
Call Stack Analysis¶
Understand execution flow:
CALL STACK panel shows:
processBlock() at AudioProcessor.cpp:142 <-- Current frame
process() at VST3Wrapper.cpp:89
runAudio() at ReaperHost.cpp:234
audioThread() at AudioEngine.cpp:56
Actions:
- Click frame to view code at that level
- Inspect variables at each frame
- Understand how you got to current line
Memory Debugging (Valgrind - Linux)¶
Detect memory leaks:
{
"name": "Debug with Valgrind",
"type": "cppdbg",
"request": "launch",
"program": "/usr/bin/valgrind",
"args": [
"--leak-check=full",
"--track-origins=yes",
"${workspaceFolder}/build/Debug/AudioLab_Tests"
],
"cwd": "${workspaceFolder}",
"MIMode": "gdb"
}
Output:
==12345== LEAK SUMMARY:
==12345== definitely lost: 512 bytes in 1 blocks
==12345== indirectly lost: 0 bytes in 0 blocks
Use Case: Find memory leaks before plugin release.
Core Dump Analysis (Linux)¶
Debug crash after it happens:
1. Enable core dumps:
2. Reproduce crash (generates core file)
3. Debug configuration:
{
"name": "Debug Core Dump",
"type": "cppdbg",
"request": "launch",
"program": "${workspaceFolder}/build/Debug/MyPlugin.so",
"args": [],
"cwd": "${workspaceFolder}",
"MIMode": "gdb",
"coreDumpPath": "${workspaceFolder}/core"
}
4. Analyze: - Call stack shows crash location - Inspect variables at crash time - Identify root cause
Troubleshooting¶
Issue 1: Breakpoints Not Hitting¶
Symptoms: - Breakpoint icon hollow (not filled) - Execution doesn't pause at breakpoint
Solutions:
1. Verify Debug Build:
# Check build type
cmake -DCMAKE_BUILD_TYPE=Debug ..
# Verify symbols exist (Windows)
dumpbin /HEADERS MyPlugin.dll | findstr "debug"
# Verify symbols exist (macOS)
dsymutil MyPlugin.vst3
# Verify symbols exist (Linux)
file MyPlugin.so
# Should say: "with debug_info, not stripped"
2. Check Source Matches Binary:
3. Verify Debugger Attached:
DEBUG CONSOLE should show:
Loaded 'MyPlugin.vst3'. Symbols loaded.
If not loaded:
- Check path to plugin
- Verify plugin loaded in DAW
- Try "Attach to Process" instead
4. Check Optimization Level:
# CMakeLists.txt - Debug build should have:
set(CMAKE_CXX_FLAGS_DEBUG "-g -O0") # No optimization
# If -O2 or -O3: Debugger may skip lines
# Solution: Use -O0 for Debug builds
Issue 2: Cannot Attach to DAW¶
Symptoms: - "Failed to attach to process" error - DAW not in process list
Solutions:
1. Run VS Code as Same User:
2. Check Process ID:
# Find DAW process
# Windows
tasklist | findstr Reaper
# macOS
ps aux | grep Reaper
# Linux
ps aux | grep reaper
# Use PID in attach config:
"processId": "12345"
3. Verify Debugger Permissions:
4. Try Launch Instead of Attach:
Instead of attaching to running DAW:
- Close DAW
- Use "Debug Plugin (Reaper)" launch config
- Let VS Code launch DAW
Issue 3: Slow Debugging (Stepping Takes Forever)¶
Symptoms: - F10/F11 takes 5+ seconds - UI freezes during debugging
Solutions:
1. Disable Lazy Symbol Loading:
{
"symbolLoadInfo": {
"loadAll": false,
"exceptionList": "MyPlugin.dll" // Only load plugin symbols
}
}
2. Optimize Build for Debugging:
3. Use RelWithDebInfo Build:
# Instead of Debug, use:
cmake -DCMAKE_BUILD_TYPE=RelWithDebInfo ..
# Optimized but with symbols
# Trade-off: Some variables optimized away
4. Reduce Pretty-Printing:
{
"setupCommands": [
{
"text": "-enable-pretty-printing",
"ignoreFailures": true
},
{
"text": "set print elements 100" // Limit array size
}
]
}
Issue 4: Variables Show "Optimized Away"¶
Symptoms:
- Variable shows <optimized out> in debugger
- Cannot inspect value
Solutions:
1. Use Debug Build (No Optimization):
2. Mark Variable as Volatile (Temporary):
volatile float myValue = calculateSomething();
// Prevents compiler from optimizing away
// Remove after debugging
3. Use Watch Expression:
Instead of inspecting variable directly:
Add watch: "this->parameterValue"
May show value even if variable optimized
4. Use RelWithDebInfo:
Issue 5: DAW Crashes When Debugger Attached¶
Symptoms: - DAW starts, then immediately crashes - "Access violation" or segfault
Solutions:
1. Disable Just-In-Time Compilation:
Some DAWs (Logic, Ableton) use JIT
JIT conflicts with debugger
Solution: Disable JIT in DAW settings (if available)
2. Check Code Signing (macOS):
# Debug builds must be signed
codesign -s - MyPlugin.vst3
# Verify signature
codesign -vvv MyPlugin.vst3
3. Disable Address Space Layout Randomization:
4. Try Different Debugger:
Best Practices¶
1. Use Pre-Launch Tasks¶
Always build before debugging:
Benefit: Ensures latest code is debugged.
2. Create DAW Test Projects¶
Save time loading plugins:
Create: test_projects/debug.rpp (Reaper)
Pre-load plugin on track
Save project
Reference in launch config:
"args": ["${workspaceFolder}/test_projects/debug.rpp"]
3. Use Conditional Breakpoints¶
Avoid stopping on every iteration:
Saves time: Stops only when condition met.
4. Use Logpoints for High-Frequency Code¶
Audio processing runs 100+ times/sec:
void processBlock(AudioBuffer<float>& buffer)
{
// Logpoint (not breakpoint):
// "Processing {buffer.getNumSamples()} samples"
// Prints to console without pausing
}
5. Organize Configurations by Use Case¶
Group similar configs:
{
"configurations": [
// Plugin Debugging
{ "name": "Debug Plugin (Reaper)" },
{ "name": "Debug Plugin (Logic)" },
// Test Debugging
{ "name": "Debug Unit Tests" },
{ "name": "Debug Audio Tests" },
// Advanced
{ "name": "Attach to Process" }
]
}
Integration with Tasks¶
Pre-launch builds (see tasks/README.md):
{
"name": "Debug Plugin (Reaper)",
"preLaunchTask": "Build: Debug", // Runs task before launch
"postDebugTask": "Clean Up" // Runs after debug session
}
Task dependency chain:
preLaunchTask: "Build: Debug"
↓
Build task runs
↓
Build completes
↓
Plugin copied to VST3 folder (CMake post-build)
↓
Debugger launches DAW
↓
DAW loads plugin
↓
Breakpoints active
Related Documentation¶
- tasks/README.md - Build tasks and automation
- keybindings/README.md - Debug keyboard shortcuts
- settings/README.md - C++ and CMake settings
- VS Code Debugging
Last Updated: October 2024 Version: 1.0.0 Maintained by: AudioLab DevOps Team
Questions? Ask in #debugging Discord channel or open GitHub issue.