Cxxdroid 中文文档 下载 App

程序一运行就崩溃怎么查 —— 从 Segfault 到崩溃日志

崩溃的三种常见类型

类型表现常见原因
Segfault屏幕闪一下黑窗口然后消失空指针解引用、数组越界、野指针
abort()控制台显示 "terminate called after throwing..."异常没捕获、assert 失败、std::terminate
OOM (OutOfMemory)应用被系统直接杀掉内存泄漏、创建了超大的 SDL 纹理

第一步:开启调试模式重跑

最简单也最有效的第一步——不要直接 Run,用 Debug 模式运行:

  1. 确认编译选项里开启了 -g(带调试符号)和 -O0(关闭优化)
  2. 在代码里不设断点,直接点 Debug
  3. 程序崩溃时,gdb 会在崩溃行自动停住
  4. 查看:当前停在哪一行、各变量的值、调用栈

如果 gdb 能在崩溃行停住,问题基本就定位了。

第二步:看崩溃日志

如果 Debug 模式也崩溃得太快、gdb 没抓到,看崩溃日志:

Android 的 logcat

在电脑上通过 adb logcat(需要 USB 调试开启)过滤:

adb logcat -s DEBUG *:S -c
adb logcat -s DEBUG

或者在手机上装一个「Logcat 查看器」类的 App,过滤 Cxxdroid 相关的崩溃信息。

典型的 Segfault 日志片段:

I/DEBUG (  1234): signal 11 (SIGSEGV), code 1 (SEGV_MAPERR), fault addr 0xdeadbeef
I/DEBUG (  1234):     #00 pc 00001234  /data/data/ru.iiec.cxxdroid/files/build/mygame
I/DEBUG (  1234):     #01 pc 00001567  /data/data/ru.iiec.cxxdroid/files/build/mygame

Cxxdroid 的控制台输出

有些崩溃(特别是 abort 和 C++ 异常)Cxxdroid 的控制台会直接打印 backtrace:

terminate called after throwing an instance of 'std::runtime_error'
  what():  something went wrong
Aborted

看到 what() 里的内容直接能定位问题。

第三步:检查最常见的崩溃原因

空指针解引用

Node *head = nullptr;
head->next = something;  // Segfault!

调试器能直接抓到——停在这行时 head 显示为 0x0,一眼就能看到。

数组越界

int arr[3] = {1, 2, 3};
arr[100] = 42;  // Segfault 或静默损坏

越界不一定立即崩溃——可能运行几分钟后才在完全不相关的地方 crash。这叫内存踩踏,最难调。用 AddressSanitizer(ASan)能直接检测。

在 CMake 里开启 ASan:

target_compile_options(myexe PRIVATE -fsanitize=address -g)
target_link_options(myexe PRIVATE -fsanitize=address)

ASan 运行时一旦检测到越界、use-after-free、double free 等问题,会精确报告:哪一行代码、什么类型的错误、附近的内存布局。比 gdb 强得多。

use-after-free

int *p = new int(5);
delete p;
std::cout << *p;  // 读已释放内存 → 崩溃或脏数据

同样用 ASan 检测。

SDL 纹理 / 窗口创建失败没检查

SDL_Window *win = SDL_CreateWindow(...);
SDL_Renderer *ren = SDL_CreateRenderer(win, -1, 0);
// 没检查 win 和 ren 是否为 null!
SDL_RenderClear(ren);  // 如果 ren 是 null → Segfault

SDL 的任何创建函数都必须检查返回值:

SDL_Window *win = SDL_CreateWindow(...);
if (!win) {
    std::cerr << "SDL_CreateWindow failed: " << SDL_GetError() << "\n";
    return 1;
}

Android 存储 / 权限问题

Cxxdroid 2026 版支持 SAF 之前的版本,如果项目放在外部存储但 Cxxdroid 没权限读取,打开文件会返回 null → 后续操作崩溃。

检查:项目目录放在 Cxxdroid 默认的内部存储里试试能不能正常跑。

终极手段:注释二分法

如果以上都试过了还定位不到:

  1. 把代码注释掉一半,跑剩下一半
  2. 如果不崩了,说明问题在被注释掉的那一半
  3. 把那一半再对半注释,继续缩小范围
  4. 直到定位到具体几行

虽然笨但绝对有效——再复杂的崩溃都能在 10 轮内定位。