Native C++ doesn't hand you a stack trace when it falls over. It hands you a memory dump, if you're lucky, and a pile of addresses that mean nothing until they're symbolicated against the exact build that crashed. That gap is where most C++ crash debugging goes to die: you have the dump, you have the binary, and somewhere in between is the version mismatch that makes the whole thing useless.

Closing that gap is what BugSplat was built to do, and it's the work we've been doing longest. C++ crash reporting is the heart of the product. You add our library to your application, it catches the crash, captures a minidump, and turns it into a grouped, symbolicated call stack with function names and line numbers in a dashboard your whole team can read. Not a log file. The actual line where it broke.

The native SDK, not a handler you wire up yourself

This is worth being clear about, because it's the difference between BugSplat and most of the alternatives. Our Windows C++ integration isn't a thin wrapper around an open-source crash handler that you have to build, configure, and babysit. It's a real SDK: you link BugSplat.lib, include BugSplat.h, and create a BugSplat instance with three parameters, your database, application name, and version.

#include "BugSplat.h"
BugSplat g_BugSplat(BUGSPLAT_DATABASE, APPLICATION_NAME, APPLICATION_VERSION);

That's the integration. One global instance, declared once, and your application is now catching unhandled crashes and posting them to BugSplat. The MyConsoleCrasher sample in the SDK lets you see the whole thing working before you touch your own code, force a crash with a command-line flag, watch the report land.

Because it's a real library rather than a bare handler, you get things the build-it-yourself route makes you assemble by hand:

  • A crash dialog out of the box. When your app crashes, the user sees a proper BugSplat dialog where they can add a description of what they were doing, context you'd otherwise never get. Or run it in quiet mode and report silently, your call.
  • Windows Error Reporting integration. Register BugSplat as a WER RuntimeExceptionModule and catch crashes that happen too early or too hard for an in-process handler to see. This is the kind of edge case that separates "catches most crashes" from "catches the crash that's actually killing you," and it's what makes the SDK work cleanly for WinUI 3 apps too.
  • CRT exception handling. Helper functions configure C Runtime exception handlers globally and per-thread, so the messy low-level failures get caught instead of slipping through.
  • Full memory dumps when you need them. Default minidumps keep uploads small, but for the crash you can't crack any other way, flip on full memory dumps for a specific version and get the complete picture. Turn it back off when you're done, since the larger files cost your users upload time.
  • Custom attributes, attachments, and notes. Attach a log file, tag the report with the build flavor or the level or the GPU, set notes your team can read later. The context that turns "it crashed" into "it crashed here, for these users, doing this."
  • User feedback, not just crashes. The same library collects non-crashing bug reports and feature requests, so the "this looked wrong but didn't crash" reports land in the same place as everything else.

Symbols are the one thing to get right

The integration is the easy part. The part that trips people up is symbols, and it's the same on every platform: if your symbols don't match the binary that crashed, byte for byte, you get addresses instead of answers.

So build your release builds with debug information (set Debug Information Format to Program Database, /Zi), and upload your .exe, .dll, and .pdb files on every release. The cleanest way is a post-build step using our symbol-upload tool, authenticated with an OAuth Client ID and Secret you generate on the Integrations page:

symbol-upload-windows.exe -b your-database -a your-app -v your-version -i your-client-id -s your-client-secret -d "$(OutputDir)\"

Wire that into your build once and you never think about it again. Skip it and you'll be staring at a hex address during a launch, wondering why the report you waited for can't tell you anything. Fresh symbols, every build. That's the whole discipline.

Ships on more than Windows? So do we.

Your native code probably doesn't stop at Windows, and neither does BugSplat. We have first-class native integrations for macOS and Linux, each with its own setup and the same symbol-upload tooling, so a crash on a Linux box you've never seen lands in the same dashboard as your Windows reports, symbolicated the same way. Mobile C++ through the Android NDK and iOS is covered too. Under the hood, our cross-platform native support is built on the open-source Crashpad handler, one handler, every platform, and we've written a full guide on building and integrating it, including our CTO Bobby's walkthrough on building Crashpad from scratch.

All told, BugSplat has native integrations across 25+ platforms and languages, desktop, mobile, web, and game consoles, all feeding one dashboard. So wherever your C++ runs, there's a real integration waiting, not a gap you have to fill yourself. On Windows specifically, the native SDK above is the richest, friendliest path. Everywhere else, you're still covered.

Building a game? There's a deeper story here

If your C++ is going into a game, this is worth a detour. Most of what's above applies, native crashes, minidumps, symbolication, but game development is its own world, and it's the one we've spent the most time in. Games ship on consoles, run custom and commercial engines, and crash on hardware your test machines never saw. Generic crash tools were built for web and mobile and bolted onto native afterward. We went the other way.

So if you're building with Unreal or Unity, we have dedicated plugins that hook straight into the engine's own crash pipeline. If you're on a custom or in-house engine, our native C++ SDK and Crashpad support are exactly what you'd build on. And if you ship on Xbox, PlayStation, or Switch 2, we cover all of them, including backwards compatibility. The C++ fundamentals you just read are the foundation. The game development integrations are where they really come alive.

And when something doesn't go to plan, you talk to us

Here's the part that doesn't show up in a feature list. BugSplat is built and maintained by a small, bootstrapped team, and that shapes the whole experience of using it. When you hit a snag integrating the C++ SDK, a symbol upload that won't resolve, a WER registration that isn't firing, a crash that's grouping in a way you don't expect, you're not filing a ticket into a queue and hoping. You reach out, and you hear back from someone who works on the product every day and has been here for close to a decade.

Everyone here handles support, so the person who answers your question helped build the thing you're asking about. Being bootstrapped is what makes that possible: our customers are the only reason BugSplat exists, so this is just how we work.

You shouldn't need a dedicated infrastructure team to know why your C++ application is crashing in the field. One person can wire up the SDK in an afternoon, and the whole team can read the reports without a debugger open. And if anything gets in the way, real people who give a damn are a chat message away. That's the bar we hold ourselves to.


Full native C++ setup is in the docs: docs.bugsplat.com

Want to see your own crashes symbolicated? Start a free trial and submit your first one in a few minutes. Stuck on anything? Email support@bugsplat.com or find us on Discord, you'll talk to the people who build it.