Hello Code::Blocks team,
I've encountered a severe issue where Code::Blocks 25.03 crashes immediately on startup on macOS 15 (Apple Silicon running via Rosetta 2). The crash throws an `EXC_BAD_ACCESS` (null pointer dereference) in `libcodecompletion.dylib`.
Root Cause Analysis:
The crash is caused by an initialization order / timing issue during startup on macOS.
When `CodeCompletion::OnAttach()` calls `m_ParseManager.CreateClassBrowser()`, the application subsystems (specifically `ProjectManager` and its Notebook UI) are not fully initialized yet.
1. `ParseManager::CreateClassBrowser()` attempts to get the notebook from `ProjectManager`, but it may not be ready.
2. Later, it calls `m_ClassBrowser->SetParser(m_Parser)`.
3. Inside `ClassBrowser::SetParser()`, it unconditionally calls `UpdateClassBrowserView()`, which attempts to access `Manager::Get()->GetProjectManager()` and crashes.
4. Additionally, the `ClassBrowser` constructor tries to fetch the ImageList without checking if `m_ParseManager` is valid.
Proposed Patch:
I've compiled a patched version locally and it completely resolves the crash, allowing CodeCompletion to work perfectly on macOS. We just need to add defensive null-pointer checks in `classbrowser.cpp` and `parsemanager.cpp`.
Here is the diff against the SVN trunk:
--- src/plugins/codecompletion/classbrowser.cpp
+++ src/plugins/codecompletion/classbrowser.cpp
@@ -176,8 +176,15 @@
m_CCTreeCtrlBottom = XRCCTRL(*this, "treeMembers", CCTreeCtrl);
// Registration of images
- m_CCTreeCtrl->SetImageList(m_ParseManager->GetImageList(16));
- m_CCTreeCtrlBottom->SetImageList(m_ParseManager->GetImageList(16));
+ if (m_ParseManager)
+ {
+ wxImageList* imgList = m_ParseManager->GetImageList(16);
+ if (imgList)
+ {
+ m_CCTreeCtrl->SetImageList(imgList);
+ m_CCTreeCtrlBottom->SetImageList(imgList);
+ }
+ }
ConfigManager* cfg = Manager::Get()->GetConfigManager("code_completion");
const int filter = cfg->ReadInt("/browser_display_filter", bdfFile);
@@ -239,12 +246,19 @@
{
const int sel = XRCCTRL(*this, "cmbView", wxChoice)->GetSelection();
BrowserDisplayFilter filter = static_cast<BrowserDisplayFilter>(sel);
- if (!m_ParseManager->IsParserPerWorkspace() && filter == bdfWorkspace)
+ if (m_ParseManager && !m_ParseManager->IsParserPerWorkspace() && filter == bdfWorkspace)
filter = bdfProject;
m_Parser->ClassBrowserOptions().displayFilter = filter;
m_Parser->WriteOptions(/*classbrowserOnly=*/true);
- UpdateClassBrowserView();
+
+ // Guard: Only update the class browser view if the application
+ // subsystems (ProjectManager, EditorManager) are fully initialized.
+ if (Manager::Get()->GetProjectManager() &&
+ Manager::Get()->GetEditorManager())
+ {
+ UpdateClassBrowserView();
+ }
}
else
CCLogger::Get()->DebugLog("SetParser: No parser available.");
--- src/plugins/codecompletion/parsemanager.cpp
+++ src/plugins/codecompletion/parsemanager.cpp
@@ -1043,9 +1043,16 @@
}
else
{
+ // Guard against ProjectManager not being ready yet (macOS startup race)
+ ProjectManager* prjMgr = Manager::Get()->GetProjectManager();
+ if (!prjMgr || !prjMgr->GetUI().GetNotebook())
+ {
+ CCLogger::Get()->DebugLog("CreateClassBrowser: ProjectManager not ready, deferring.");
+ return;
+ }
// make this a tab in projectmanager notebook
- m_ClassBrowser = new ClassBrowser(Manager::Get()->GetProjectManager()->GetUI().GetNotebook(), this);
- Manager::Get()->GetProjectManager()->GetUI().GetNotebook()->AddPage(m_ClassBrowser, _("Symbols"));
+ m_ClassBrowser = new ClassBrowser(prjMgr->GetUI().GetNotebook(), this);
+ prjMgr->GetUI().GetNotebook()->AddPage(m_ClassBrowser, _("Symbols"));
m_ClassBrowser->UpdateSash();
}
@@ -1053,7 +1060,8 @@
// TODO (Morten): ? what's bug? I test it, it's works well now.
- m_ClassBrowser->SetParser(m_Parser); // Also updates class browser
+ if (m_Parser)
+ m_ClassBrowser->SetParser(m_Parser); // Also updates class browser
TRACE(_T("ParseManager::CreateClassBrowser: Leave"));
}
Hope this helps improve macOS stability. Let me know if you need any more information!