Recently, I've been running a pgm under the debugger that
causes CB to crash when I delete a breakpoint. But the pgm runs ok when not being debugged. (famous saying)
So I placed asm(int3) traps until I bracketed the problem.
It seems that GdbCmd_RemoveBreakpoint::ParseOutput is assigning
a -1 to a breakpoint that has already been deleted.
Here is a way to reproduce the error.
I do not know the debugger well enough to know how to fix it.
In debuggerstate.cpp at line 191, place a trap and note
the bp address that's being deleted.
DebuggerBreakpoint* DebuggerState::RemoveBreakpoint(int idx, bool deleteit)
{
// do we have a valid index?
if (idx < 0 || idx >= (int)m_Breakpoints.GetCount())
return 0;
// yes, remove it from the list
DebuggerBreakpoint* bp = m_Breakpoints[idx];
m_Breakpoints.RemoveAt(idx);
// notify driver if it is active
if (m_pDriver)
m_pDriver->RemoveBreakpoint(bp);
if (deleteit)
{
asm("int3"); /*trap*/ //<===============
delete bp; //<= look at bp address
return 0;
}
return bp;
}
In gdb_command.h at line 777, place the following trap.
When the debugger stops at "cmd->ParseOutput(buffer.Left(idx));"
step into the GdbCmd_RemoveBreakpoint() routine and
look at m_BP of the line: "m_BP->index = -1;".
m_BP is the exact address of the bp that got previously deleted.
class GdbCmd_RemoveBreakpoint : public DebuggerCmd
{
< lines skipped>
// DebugLog(wxString::Format(_T("Command parsing output (cmd: %s): %s"), cmd->m_Cmd.c_str(), buffer.Left(idx).c_str()));
RemoveTopCommand(false);
buffer.Remove(idx);
// remove the '>>>>>>' part of the prompt (or what's left of it)
int cnt = 6; // max 6 '>'
while (buffer.Last() == _T('>') && cnt--)
buffer.RemoveLast();
if (buffer.Last() == _T('\n'))
buffer.RemoveLast();
wxString cmdString = cmd->m_Cmd; /*trap*/
if (cmdString.StartsWith(_T("delete "))) asm("int3"); /*trap*/
cmd->ParseOutput(buffer.Left(idx));
delete cmd;
RunQueue();
}
This is the culprit: line 508 in gdb_commands.h . m_BP has already been deleted.
// invalidate bp number
m_BP->index = -1;
Although there's a test for m_BP, it's never zero. It seems to be a copy of the original bp.
if (!m_BP)
return;
void ParseOutput(const wxString& output)
{
if (!m_BP)
return;
// invalidate bp number
m_BP->index = -1;
if (!output.IsEmpty())
m_pDriver->Log(output);
// m_pDriver->DebugLog(wxString::Format(_("Breakpoint removed: file %s, line %d"), m_BP->filename.c_str(), m_BP->line + 1));
}
DebuggerBreakpoint* m_BP;
};