現象
- 啟動進入開始界面正常。
- 點擊「開始遊戲」按鈕後,畫面凍結/崩潰/無反應。
- 日誌無明顯 C++ 異常拋出。
核心原因:結構體/類成員指針未初始化
典型代碼模式:
struct GameData {
Sprite* hero;
Vector<Enemy*> enemies;
// 無構造函數,成員處於隨機值
};
bool GameScene::init() {
GameData data; // 棧上分配,未初始化
data.hero = Sprite::create("hero.png"); // 可能覆蓋隨機值,但 enemies 仍是野指針
// 後續使用 data.enemies.pushBack(...) 觸發 UB
}
修正方案
- **為結構體/類編寫構造函數**,將所有指針初始化為 `nullptr`,容器初始化為空。
- 或改用 **C++11 聚合初始化**:`GameData data = {};`(零初始化)。
- 關鍵成員改用智能指針(`std::unique_ptr`/`std::shared_ptr`)或 Cocos2d-x `Ref` 體系(`create`/`retain`/`release`)。
調試技巧
- 開啟 **AddressSanitizer (ASan)** 編譯選項(`-fsanitize=address`),能精準定位野指針訪問。
- 在可疑函數入口加 `CCASSERT(ptr != nullptr, "ptr null");`。
- 使用 Xcode/LLDB 或 Android Studio/LLDB 斷點調試,觀察成員變量值是否為 `0xcdcdcdcd`、`0xdddddddd` 等未初始化標記。
最佳實踐
- 所有自定義類/結構體**強制編寫構造函數**,RAII 原則管理資源。
- 避免裸指針作為成員,優先用容器、智能指針、或引擎提供的 `RefPtr`。
- 場景切換時,在 `onExit`/`cleanup` 中釋放資源,防洩漏。