diff --git a/src/common/appbase.cpp b/src/common/appbase.cpp index 93a47aad1b..cfd8bd5c41 100644 --- a/src/common/appbase.cpp +++ b/src/common/appbase.cpp @@ -1012,25 +1012,37 @@ wxString wxAppTraitsBase::GetAssertStackTrace() #endif // !__WINDOWS__ - wxString stackTrace; - class StackDump : public wxStackWalker { public: - StackDump() { } + StackDump() { m_numFrames = 0; } const wxString& GetStackTrace() const { return m_stackTrace; } protected: virtual void OnStackFrame(const wxStackFrame& frame) wxOVERRIDE { - m_stackTrace << wxString::Format - ( - wxT("[%02d] "), - wx_truncate_cast(int, frame.GetLevel()) - ); + // don't show more than maxLines or we could get a dialog too tall + // to be shown on screen: 20 should be ok everywhere as even with + // 15 pixel high characters it is still only 300 pixels... + if ( m_numFrames++ > 20 ) + return; + + m_stackTrace << wxString::Format(wxT("[%02u] "), m_numFrames); + + const wxString name = frame.GetName(); + if ( name.StartsWith("wxOnAssert") ) + { + // Ignore all frames until the wxOnAssert() one, they are + // internal to wxWidgets and not interesting for the user + // (but notice that if we never find the wxOnAssert() frame, + // e.g. because we don't have symbol info at all, we would show + // everything which is better than not showing anything). + m_stackTrace.clear(); + m_numFrames = 0; + return; + } - wxString name = frame.GetName(); if ( !name.empty() ) { m_stackTrace << wxString::Format(wxT("%-40s"), name.c_str()); @@ -1053,22 +1065,12 @@ wxString wxAppTraitsBase::GetAssertStackTrace() private: wxString m_stackTrace; + unsigned m_numFrames; }; - // don't show more than maxLines or we could get a dialog too tall to be - // shown on screen: 20 should be ok everywhere as even with 15 pixel high - // characters it is still only 300 pixels... - static const int maxLines = 20; - StackDump dump; - dump.Walk(8, maxLines); // 8 is chosen to hide all OnAssert() calls - stackTrace = dump.GetStackTrace(); - - const int count = stackTrace.Freq(wxT('\n')); - for ( int i = 0; i < count - maxLines; i++ ) - stackTrace = stackTrace.BeforeLast(wxT('\n')); - - return stackTrace; + dump.Walk(); + return dump.GetStackTrace(); #else // !wxDEBUG_LEVEL // this function is still present for ABI-compatibility even in debug level // 0 build but is not used there and so can simply do nothing diff --git a/src/gtk/utilsgtk.cpp b/src/gtk/utilsgtk.cpp index d1603d7f1a..36c5013722 100644 --- a/src/gtk/utilsgtk.cpp +++ b/src/gtk/utilsgtk.cpp @@ -20,6 +20,7 @@ #include "wx/apptrait.h" #include "wx/process.h" #include "wx/sysopt.h" +#include "wx/vector.h" #include "wx/gtk/private/timer.h" #include "wx/evtloop.h" @@ -254,30 +255,68 @@ class StackDump : public wxStackWalker public: StackDump(GtkAssertDialog *dlg) { m_dlg=dlg; } + void ShowStackInDialog() + { + ProcessFrames(0); + + for ( wxVector::const_iterator it = m_frames.begin(); + it != m_frames.end(); + ++it ) + { + gtk_assert_dialog_append_stack_frame(m_dlg, + it->name.utf8_str(), + it->file.utf8_str(), + it->line); + } + + m_frames.clear(); + } + protected: virtual void OnStackFrame(const wxStackFrame& frame) wxOVERRIDE { - wxString fncname = frame.GetName(); - - // append this stack frame's info in the dialog - if (!frame.GetFileName().empty() || !fncname.empty()) + const wxString name = frame.GetName(); + if ( name.StartsWith("wxOnAssert") ) { - gtk_assert_dialog_append_stack_frame(m_dlg, - fncname.utf8_str(), - frame.GetFileName().utf8_str(), - frame.GetLine()); + // Ignore all frames until the wxOnAssert() one, just as we do in + // wxAppTraitsBase::GetAssertStackTrace(). + m_frames.clear(); + return; } + + // Also ignore frames which don't have neither the function name nor + // the file name, showing them in the dialog wouldn't provide any + // useful information. + if ( name.empty() && frame.GetFileName().empty() ) + return; + + m_frames.push_back(Frame(frame)); } private: GtkAssertDialog *m_dlg; + + struct Frame + { + explicit Frame(const wxStackFrame& f) + : name(f.GetName()), + file(f.GetFileName()), + line(f.GetLine()) + { + } + + wxString name; + wxString file; + int line; + }; + + wxVector m_frames; }; static void get_stackframe_callback(void* p) { StackDump* dump = static_cast(p); - // skip over frames up to including wxOnAssert() - dump->ProcessFrames(6); + dump->ShowStackInDialog(); } #endif // wxDEBUG_LEVEL && wxUSE_STACKWALKER