← Back to Engineering Journal
NDK & Native Systems Published July 15, 2026 8 min read

Dissecting Signal 11 (SIGSEGV) Crashes in Android NDK Binaries

A step-by-step forensic guide to decoding tombstone files, interpreting fault addresses, and identifying memory corruption in native Android shared libraries.

Dissecting Signal 11 (SIGSEGV) Crashes in Android NDK Binaries

Understanding Fatal Native Signals

In mobile client engineering, few failure modes are as difficult to diagnose as native signal terminations. Unlike managed exceptions in Kotlin or Java which provide structured stack traces, a SIGSEGV (Segmentation Fault, Signal 11) occurs when a process attempts to access an unallocated or protected memory address.

When this occurs, the Linux kernel terminates the process immediately, dumping register state to the Android logcat or a system tombstone file.

*** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
Build fingerprint: 'google/raven/raven:13/TP1A.220624.014/8819323:user/release-keys'
Revision: 'MP1.0'
ABI: 'arm64'
Timestamp: 2026-07-14 14:32:09.112349021+0700
Process: com.example.clientapp (pid: 18492, tid: 18530)
Cmdline: com.example.clientapp
pid: 18492, tid: 18530, name: RenderThread  >>> com.example.clientapp <<<
uid: 10243
signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0x0000000000000018
    x0  0000000000000000  x1  0000007b34208a10  x2  0000000000000040  x3  0000007b34208a50
    x4  0000000000000008  x5  0000007b34208a90  x6  0000000000000000  x7  0000007b34208ad0

Decoding SEGV_MAPERR vs SEGV_ACCERR

The code field in the signal header provides the first critical clue:

  1. SEGV_MAPERR (Address not mapped to object): The process attempted to read or write to an address that does not exist in its virtual memory space. A classic example is a null-pointer dereference with a struct offset (e.g. fault addr 0x0000000000000018, indicating access to a field at offset 24 bytes from a NULL pointer).
  2. SEGV_ACCERR (Invalid permissions for mapped object): The address exists in memory, but the process lacks permissions (e.g. attempting to write to a read-only .rodata segment, or executing data on a non-executable heap page).

Unstripping Native Shared Libraries with ndk-stack

In production release builds, .so files are stripped of symbol tables (.symtab and .strtab) to reduce APK download size. When the crash occurs, stack traces display only hexadecimal program counter offsets:

#00 pc 000000000004a8bc  /data/app/.../libnative_engine.so
#01 pc 000000000003b120  /data/app/.../libnative_engine.so
#02 pc 0000000000089f44  /apex/com.android.runtime/lib64/bionic/libc.so

To resolve these offsets into file names and line numbers:

# Locate the unstripped binary produced during the release build:
# path: app/build/intermediates/merged_native_libs/release/out/lib/arm64-v8a/libnative_engine.so

$ ndk-stack -sym /path/to/unstripped/arm64-v8a/ -dump tombstone.txt

This transforms the opaque offset into concrete code lines:

#00 0x000000000004a8bc /workspace/cpp/graphics_context.cpp:142
    GraphicsContext::BindTexture(TextureHandle* handle)
#01 0x000000000003b120 /workspace/cpp/render_pipeline.cpp:89
    RenderPipeline::DrawFrame()

Common Native Root Causes & Defensive Patterns

  • Stale JNI Global References: Forgetting to promote local JNI references when passing objects across asynchronous native threads.
  • NEON SIMD Vector Alignment: Using 128-bit load instructions (vld1q_f32) against unaligned byte buffers on ARM64 hardware.
  • Use-After-Free in Callback Queues: Accessing C++ object instances after their corresponding Java finalize() or Kotlin close() method has deallocated the native pointer.

Summary

Resolving native crashes requires establishing a disciplined symbol archive pipeline during CI/CD builds and systematically inspecting register fault addresses. When automated tools fail to unstrip native stack frames, manual forensic triage uncovers the memory boundary violations beneath the surface.

Need Diagnostic Assistance on a Similar Issue?

Think Harbor Base specializes in isolating native stack corruption, high-impact ANRs, and memory regression. Inquire about an engineering audit for your application.