Do you have a backtrace?
C::B didn't create a crash.log, but I have the call stack from the debugger
#0 65EC347F NativeParser::RemoveObsoleteParsers(this=0x56c5a60) (D:\codeblocks\source\src\plugins\codecompletion\nativeparser.cpp:1257)
#1 65EBE8A8 NativeParser::CreateParser(this=0x56c5a60, project=0xecb8f60) (D:\codeblocks\source\src\plugins\codecompletion\nativeparser.cpp:590)
#2 65EAB40C CodeCompletion::OnProjectActivated(this=0x56c5a18, event=...) (D:\codeblocks\source\src\plugins\codecompletion\codecompletion.cpp:2384)
#3 65F28428 cbEventFunctor<CodeCompletion, CodeBlocksEvent>::Call(this=0x5cb5028, event=...) (D:/codeblocks/source/src/include/cbfunctor.h:35)
#4 6189A918 Manager::ProcessEvent(this=0xd9a588, event=...) (D:\codeblocks\source\src\sdk\manager.cpp:179)
#5 618B07B6 PluginManager::NotifyPlugins(this=0x2eef4f8, event=...) (D:\codeblocks\source\src\sdk\pluginmanager.cpp:1445)
#6 618D06E9 ProjectManager::SetProject(this=0xdcb368, project=0xecb8f60, refresh=true) (D:\codeblocks\source\src\sdk\projectmanager.cpp:494)
#7 618D3ADF ProjectManager::LoadProject(this=0xdcb368, filename=..., activateIt=true) (D:\codeblocks\source\src\sdk\projectmanager.cpp:792)
#8 0044A064 MainFrame::DoOpenProject(this=0xdbca38, filename=..., addToHistory=true) (D:\codeblocks\source\src\src\main.cpp:1831)
#9 00449B2F MainFrame::OpenGeneric(this=0xdbca38, filename=..., addToHistory=true) (D:\codeblocks\source\src\src\main.cpp:1780)
#10 004524AF MainFrame::OnFileReopenProject(this=0xdbca38, event=...) (D:\codeblocks\source\src\src\main.cpp:2771)
#11 705C7670 wxEvtHandler::ProcessEventIfMatches(wxEventTableEntryBase const&, wxEvtHandler*, wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#12 705C77A9 wxEventHashTable::HandleEvent(wxEvent&, wxEvtHandler*) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#13 705C7B74 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#14 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#15 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#16 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#17 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#18 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#19 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#20 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#21 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#22 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#23 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#24 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#25 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#26 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#27 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#28 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#29 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
BTW: The same happens if you have loaded a couple of projects and then reduce the number of max. parsers to a number less than currently opened projects.
Ok, Thanks.
Same crash here.
crash code:
void NativeParser::RemoveObsoleteParsers()
{
TRACE(_T("NativeParser::RemoveObsoleteParsers()"));
ConfigManager* cfg = Manager::Get()->GetConfigManager(_T("code_completion"));
const size_t maxParsers = cfg->ReadInt(_T("/max_parsers"), 5);
wxArrayString removedProjectNames;
std::pair<cbProject*, ParserBase*> info = GetParserInfoByCurrentEditor();
while (m_ParserList.size() > maxParsers)
{
bool deleted = false;
for (ParserList::const_iterator it = m_ParserList.begin(); it != m_ParserList.end(); ++it)
{
if (it->second == info.second)
continue;
if (DeleteParser(it->first))
{
wxString prj = (it->first ? it->first->GetTitle() : _T("*NONE*"));
removedProjectNames.Add(prj);
deleted = true;
break;
}
}
line: wxString prj = (it->first ? it->first->GetTitle() : _T("*NONE*"));
the debug log is:
> p it
[debug]> p it
[debug]$1 = {first = , second = }
[debug]>>>>>>cb_gdb:
$1 = {first = , second = }
> p it->first
[debug]> p it->first
[debug]$2 = (cbProject *) 0xfeeefeee
[debug]>>>>>>cb_gdb:
$2 = (cbProject *) 0xfeeefeee
> p it->first->GetTitle()
[debug]> p it->first->GetTitle()
[debug]Cannot access memory at address 0xfeeefeee
[debug]>>>>>>cb_gdb:
Cannot access memory at address 0xfeeefeee
No time to analyze the bug. :)
It would better to file a bug report in BerliOS site, so it never be forgot.
BTW: which version of gdb did you use, it looks your gdb have longer backtrace them mine.
I assume that DeleteParser modify m_ParserList, so the iterator 'it' is no longer valid.
Moving
wxString prj = (it->first ? it->first->GetTitle() : _T("*NONE*"));
just before
if (DeleteParser(it->first))
should fix the issue.
I assume that DeleteParser modify m_ParserList, so the iterator 'it' is no longer valid.
Moving
wxString prj = (it->first ? it->first->GetTitle() : _T("*NONE*"));
just before
if (DeleteParser(it->first))
should fix the issue.
You are right, I just review the logic of DeleteParser(), look below:
bool NativeParser::DeleteParser(cbProject* project)
{
wxString prj = (project ? project->GetTitle() : _T("*NONE*"));
ParserList::iterator it = m_ParserList.begin();
if (!m_ParserPerWorkspace)
{
for (; it != m_ParserList.end(); ++it)
{
if (it->first == project)
break;
}
}
if (it == m_ParserList.end())
{
CCLogger::Get()->DebugLog(F(_T("NativeParser::DeleteParser(): Parser does not exist for delete '%s'!"), prj.wx_str()));
return false;
}
bool removeProjectFromParser = false;
if (m_ParserPerWorkspace)
removeProjectFromParser = RemoveProjectFromParser(project);
if (m_ParsedProjects.empty())
{
if (it->second == m_Parser)
SetParser(m_TempParser); // Also updates class browser
wxString log(F(_("NativeParser::DeleteParser(): Deleting parser for project '%s'!"), prj.wx_str()));
CCLogger::Get()->Log(log);
CCLogger::Get()->DebugLog(log);
delete it->second;
m_ParserList.erase(it);
return true;
}
if (removeProjectFromParser)
return true;
CCLogger::Get()->DebugLog(_T("NativeParser::DeleteParser(): Deleting parser failed!"));
return false;
}
Here
The element is removed.
But return from the function.
The constant iterator is reused.
I'm going to fix it by your suggestion. Thanks.
It does. CC seems to work as well for all opened projects.
Thanks for the test.
@ollydbg: using GDB 7.2
Thanks, but I see that longer bt report are some redundant lines like:
#13 705C7B74 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#14 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#15 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
#16 705C7B10 wxEvtHandler::ProcessEvent(wxEvent&) () (D:\codeblocks\source\src\devel\wxmsw28u_gcc_cb.dll:??)
...
Newer GDB(I'm using GDB CVS head) just stop unwinding in this cases. :)
Thanks for fixing.
Unfortunally, I found another one in nativeparser.cpp...
This time it happens if you open a project and *immediately* close it. The problem occures in NativeParser::OnParserStart, which seems to recceive a cbProject pointer to a project that has already been deleted (project->GetTitle refers to 0xfeeefeee).
The Backtrace (C::B Rev 8900) is:
#0 00000000 0xfeeefeee in ??() (??:??)
#1 65ECCBD3 NativeParser::OnParserStart(this=0x32bd5b0, event=...) (D:\projekte\codeblocks\source2\src\plugins\codecompletion\nativeparser.cpp:2458)
#2 705C7670 wxEvtHandler::ProcessEventIfMatches(wxEventTableEntryBase const&, wxEvtHandler*, wxEvent&) () (D:\projekte\codeblocks\source2\src\devel\wxmsw28u_gcc_cb.dll:??)
#3 705C7A96 wxEvtHandler::SearchDynamicEventTable(wxEvent&) () (D:\projekte\codeblocks\source2\src\devel\wxmsw28u_gcc_cb.dll:??)
#4 705C7B4B wxEvtHandler::ProcessEvent(wxEvent&) () (D:\projekte\codeblocks\source2\src\devel\wxmsw28u_gcc_cb.dll:??)
#5 65EF4C49 Parser::ProcessParserEvent(this=0x11503218, state=ParserCommon::ptCreateParser, id=1391, info=...) (D:\projekte\codeblocks\source2\src\plugins\codecompletion\parser\parser.cpp:1178)
#6 65EF3449 Parser::OnBatchTimer(this=0x11503218, event=...) (D:\projekte\codeblocks\source2\src\plugins\codecompletion\parser\parser.cpp:1078)
#7 705C7670 wxEvtHandler::ProcessEventIfMatches(wxEventTableEntryBase const&, wxEvtHandler*, wxEvent&) () (D:\projekte\codeblocks\source2\src\devel\wxmsw28u_gcc_cb.dll:??)
#8 705C7A96 wxEvtHandler::SearchDynamicEventTable(wxEvent&) () (D:\projekte\codeblocks\source2\src\devel\wxmsw28u_gcc_cb.dll:??)
#9 705C7B4B wxEvtHandler::ProcessEvent(wxEvent&) () (D:\projekte\codeblocks\source2\src\devel\wxmsw28u_gcc_cb.dll:??)
#10 706D70ED wxTimerBase::Notify() () (D:\projekte\codeblocks\source2\src\devel\wxmsw28u_gcc_cb.dll:??)
#11 70607BDC wxTimerWndProc() (D:\projekte\codeblocks\source2\src\devel\wxmsw28u_gcc_cb.dll:??)
#12 75CC6238 USER32!IsDialogMessageW() (C:\Windows\syswow64\user32.dll:??)
#13 00000000 0x000309a8 in ??() (??:??)
#14 75CC68EA USER32!AllowForegroundActivation() (C:\Windows\syswow64\user32.dll:??)
#15 70607B64 wxProcessTimer(wxTimer&) () (D:\projekte\codeblocks\source2\src\devel\wxmsw28u_gcc_cb.dll:??)
#16 75CC7D31 USER32!GetMessageExtraInfo() (C:\Windows\syswow64\user32.dll:??)
#17 00000000 0x00000000 in ??() (??:??)
I get similar crash, but not the same bt as yours.
Q:
cbProject* ProjectManager::LoadProject(const wxString& filename, bool activateIt)
{
cbProject* result = 0;
if (!wxFileExists(filename) || !BeginLoadingProject())
{
return 0;
}
// "Try" block (loop which only gets executed once)
// These blocks are extremely useful in constructs that need
// premature exits. Instead of having multiple return points,
// multiple return values and/or gotos,
// you just break out of the loop (which only gets executed once) to exit.
do
{
cbProject* project = IsOpen(filename);
if (project)
{
// already open
result = project;
break;
}
if (FileTypeOf(filename) == ftCodeBlocksProject)
{
project = new cbProject(filename);
// We need to do this because creating cbProject allows the app to be
// closed in the middle of the operation. So the class destructor gets
// called in the middle of a method call.
if (!project->IsLoaded())
{
delete project;
break;
}
result = project;
}
else // !ftCodeBlocksProject
{
// the plugin handler should call begin/end on its own...
EndLoadingProject(0);
cbMimePlugin* plugin = Manager::Get()->GetPluginManager()->GetMIMEHandlerForFile(filename);
if (plugin)
plugin->OpenFile(filename);
}
break;
} while (false);
// we 're done
EndLoadingProject(result);
if (activateIt)
{
if (m_IsLoadingWorkspace)
// postpone the call to SetProject() until EndLoadingWorkspace() is called
// (we must call RebuildTree() before SetProject() is called)
m_pProjectToActivate = result;
else
SetProject(result, true);
}
return result;
}
I don't understand this comment.
// We need to do this because creating cbProject allows the app to be
// closed in the middle of the operation. So the class destructor gets
// called in the middle of a method call.
if (!project->IsLoaded())
{
delete project;
break;
}
The project may be deleted when loading? I don't know how it did.