Skip to content

Windows: app built with Debug CRT (/MDd) + prebuilt SDK (Release CRT) crashes with access violation inside Room::connect() — please add a CMake runtime-library guard #250

Description

@luzz233

LiveKit C++ SDK Version

v1.10.0 (prebuilt asset livekit-sdk-windows-x64-1.10.0, linked via LiveKitSDK.cmake / find_package(LiveKit))

Platform

Windows x64

OS Version

Windows 11 Home (10.0.26200)

Compiler & Version

MSVC v143 — Visual Studio Community 2022 (17.14.36623.8), Windows 10 SDK 10.0.26100

CMake Version

3.31.6 (VS bundled, 3.31.6-msvc6)

How are you using the SDK?

Pre-built release package (find_package(LiveKit CONFIG))

Issue Description

Environment

  • SDK: v1.10.0 prebuilt asset (livekit-sdk-windows-x64-1.10.0, find_package(LiveKit) via the CMake helper)
  • Host app: Flutter Windows runner with a hand-written Win32 call window linking the SDK, built with flutter build windows --debug → exe linked against /MDd (ucrtbased / vcruntime140d / msvcp140d)
  • OS: Windows 11, VS 2022 (v143)
  • livekit.dll from the prebuilt package links the Release CRT (vcruntime140 / msvcp140)

Summary

Linking the prebuilt SDK into an application compiled with the Debug CRT (/MDd) compiles
and links cleanly, and basic FFI-only calls work — but Room::connect(url, token, options)
crashes the process instantly with an access violation (0xC0000005), with no dialog, no
exception, and nothing catchable. This is the classic Debug/Release CRT mismatch, but
nothing warns about it at configure/build time, so it surfaces as a silent runtime crash
that is very expensive to diagnose.

Repro

  1. Create any Windows app configured with /MDd (e.g. a Flutter Windows app built with
    flutter build windows --debug, or a plain CMake app with
    set(CMAKE_MSVC_RUNTIME_LIBRARY MultiThreadedDebugDLL)).
  2. Link the prebuilt SDK.
  3. Minimal sequence:
livekit::initialize(livekit::LogLevel::Info);
livekit::Room room;
bool ok = room.connect(url, token, livekit::RoomOptions{});  // 💥 instant AV

Note the interesting split that confirms the boundary nature:

  • livekit::PlatformAudio p; — succeeds (FFI-only path, no C++ objects cross the DLL boundary)
  • room.connect(const std::string&, const std::string&, const RoomOptions&) — instant crash
    (first call where STL objects cross the exe↔DLL boundary)

What the crash looks like

  • SEH exception 0xC0000005, read of address 0xFFFFFFFFFFFFFFFF
  • Exception address: livekit.dll+0x3ee63 (inside the SDK, not in app code, not in livekit_ffi)
  • Disassembly around the crash (function bounds from .pdata, SDK has no PDBs):
mov  rdi, qword ptr [r14 + 0x68]     ; pull a "pointer" from a container slot
cmp  rdi, r15                        ; iterate
...
cmp  qword ptr [rdi + 0x10], 0       ; 💥 AV: rdi == 0xFFFFFFFFFFFFFFEF (garbage)
...
cmp  qword ptr [rdi + 0x18], 0xf     ; MSVC std::string SSO capacity check

i.e. the Release-compiled SDK code walks a container and dereferences a garbage pointer
where it expects a std::string. A Debug-built app passing std::string/RoomOptions
(by const ref) into the Release-compiled DLL results in diverging STL layouts
(_ITERATOR_DEBUG_LEVEL=2 guard fields in Debug vs none in Release), so fields are read
at wrong offsets.

Building the same app with the Release runtime (e.g. flutter build windows --profile)
makes everything work — same SDK, same code, no other changes.

Ask

  1. Add a configure/build-time guard. In the SDK's CMake config (or the
    LiveKitSDK.cmake download helper), when the consuming target uses the MSVC Debug
    runtime (CMAKE_MSVC_RUNTIME_LIBRARY contains Debug, or /MDd is detected),
    emit a FATAL_ERROR (or at minimum WARNING) stating that the prebuilt binaries
    are Release-CRT-only and Debug apps must build the SDK from source or switch to a
    Release runtime. This turns a silent runtime crash into a one-line actionable error.
  2. Alternatively/additionally, note the limitation in README / DEPENDENCIES.md
    (DEPENDENCIES.md currently covers missing-runtime-dependency crashes but not the
    Debug/Release CRT mix).
  3. (Nice to have) Publish Debug variants of the prebuilt assets — though I understand
    this doubles the release matrix since livekit_ffi.dll would need a matching Debug build.

Workaround (for anyone finding this)

  • Build your app against the Release CRT: for Flutter, flutter build windows --profile
    (or --release); for plain CMake, MultiThreadedDLL / MultiThreadedReleaseDLL.
  • Or build the SDK from source with a matching Debug configuration.

Steps to Reproduce

No response

Logs

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

No labels
No labels

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions