Discovered following compiler bug:
case bsTargetDone:
{
// get next build job
if (m_BuildJob != bjTarget)
{
BuildJobTarget& bj = PeekNextJob(); // <--------------- reference
if (bj.project && bj.project == m_pBuildingProject)
{
// same project, switch target
bj = GetNextJob(); // remove job from queue // <-------- refers to deleted memory
m_BuildingTargetName = bj.targetName;
// switching targets
if (clean && !build)
return bsTargetClean;
return bsTargetPreBuild;
}
// switch project
// don't run postbuild step, if we only clean the project
if (build)
return bsProjectPostBuild;
return bsProjectDone;
}
m_pBuildingProject->SetCurrentlyCompilingTarget(0);
break; // all done
}
should be
case bsTargetDone:
{
// get next build job
if (m_BuildJob != bjTarget)
{
BuildJobTarget bj = PeekNextJob(); <---------- fix
if (bj.project && bj.project == m_pBuildingProject)
{
// same project, switch target
GetNextJob(); // remove job from queue <---------- fix
m_BuildingTargetName = bj.targetName;
// switching targets
if (clean && !build)
return bsTargetClean;
return bsTargetPreBuild;
}
// switch project
// don't run postbuild step, if we only clean the project
if (build)
return bsProjectPostBuild;
return bsProjectDone;
}
m_pBuildingProject->SetCurrentlyCompilingTarget(0);
break; // all done
}
Perhaps I found actual first snippet for proper trunk. This was discovered by bulk project compiling using script console. Always crashed after 21 projects compiled.
CompilerGCC::BuildJobTarget& CompilerGCC::PeekNextJob()
{
static BuildJobTarget ret;
ret = BuildJobTarget();
if (m_BuildJobTargetsList.empty())
return ret;
return m_BuildJobTargetsList.front();
}
but the instance returned is
m_BuildJobTargetsList.front();
and it is assigned to reference. So I think it refers to same place a not to temporary place. I dont know how the front() is solved internally.
comsytec:
Can you try this patch and tell me if it fixes the problem for you?
Also can you provide a simple workspace that can be used to reproduce the problem?
Index: src/plugins/compilergcc/compilergcc.cpp
===================================================================
--- src/plugins/compilergcc/compilergcc.cpp (revision )
+++ src/plugins/compilergcc/compilergcc.cpp (working copy)
@@ -2175,12 +2175,12 @@ BuildState CompilerGCC::GetNextStateBasedOnJob()
// get next build job
if (m_BuildJob != bjTarget)
{
- BuildJobTarget& bj = PeekNextJob();
+ const BuildJobTarget& bj = PeekNextJob();
if (bj.project && bj.project == m_pBuildingProject)
{
// same project, switch target
- bj = GetNextJob(); // remove job from queue
m_BuildingTargetName = bj.targetName;
+ GetNextJob(); // remove job from queue, bj points to a destructed object
// switching targets
if (clean && !build)
return bsTargetClean;
@@ -2540,10 +2540,9 @@ CompilerGCC::BuildJobTarget CompilerGCC::GetNextJob()
return ret;
}
-CompilerGCC::BuildJobTarget& CompilerGCC::PeekNextJob()
+const CompilerGCC::BuildJobTarget& CompilerGCC::PeekNextJob()
{
static BuildJobTarget ret;
- ret = BuildJobTarget();
if (m_BuildJobTargetsList.empty())
return ret;
Index: src/plugins/compilergcc/compilergcc.h
===================================================================
--- src/plugins/compilergcc/compilergcc.h (revision )
+++ src/plugins/compilergcc/compilergcc.h (working copy)
@@ -252,7 +252,7 @@ class CompilerGCC : public cbCompilerPlugin
void ExpandTargets(cbProject* project, const wxString& targetName, wxArrayString& result);
void PreprocessJob(cbProject* project, const wxString& targetName);
BuildJobTarget GetNextJob();
- BuildJobTarget& PeekNextJob();
+ const BuildJobTarget& PeekNextJob();
struct CompilerProcess
{