mirror of git://gcc.gnu.org/git/gcc.git
libstdc++: Improve ostream output for std::stacktrace
With this change stacktrace entries always output the frame address, and source file information no longer results in " at :0", e.g. 16# myfunc(int) at /tmp/bt.cc:48 [0x4008b7] 17# main at /tmp/bt.cc:61 [0x40091a] 18# __libc_start_call_main [0x7efc3d6d3574] 19# __libc_start_main@GLIBC_2.2.5 [0x7efc3d6d3627] 20# _start [0x400684] This replaces the previous output: 16# myfunc(int) at /tmp/bt.cc:48 17# main at /tmp/bt.cc:61 18# __libc_start_call_main at :0 19# __libc_start_main@GLIBC_2.2.5 at :0 20# _start at :0 A change that is not visible in the examples above is that for a non-empty stacktrace_entry, we now print "<unknown>" for the function name if description() returns an empty string. For an empty (e.g. default constructed) stacktrace_entry the entire string representation is now "<unknown>" instead of an empty string. Instead of printing "<unknown>" for the function name, we could set that string in the stacktrace_entry::_Info object, so that description() returns "<unknown>" and then operator<< wouldn't need to handle an empty description() string. However, returning an empty string from that function seems simpler for users to detect, rather than having to parse "<unknown>". We could also choose a different string for an empty stacktrace_entry, maybe "<none>" or "<invalid>", but "<unknown>" seems good. libstdc++-v3/ChangeLog: * include/std/stacktrace (operator<<(ostream&, const stacktrace_entry&)): Improve output when description() or source_file() returns an empty string, or the stacktrace_entry is invalid. Append frame address to output. (operator<<(ostream&, const basic_stacktrace<A>&)): Use the size_type of the correct specialization. Reviewed-by: Tomasz Kamiński <tkaminsk@redhat.com> Reviewed-by: Nathan Myers <nmyers@redhat.com>
This commit is contained in:
parent
dfb7e97dd2
commit
08b2c542e4
|
@ -683,13 +683,32 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
inline ostream&
|
inline ostream&
|
||||||
operator<<(ostream& __os, const stacktrace_entry& __f)
|
operator<<(ostream& __os, const stacktrace_entry& __f)
|
||||||
{
|
{
|
||||||
|
if (!__f) [[unlikely]]
|
||||||
|
return __os << "<unknown>";
|
||||||
|
|
||||||
string __desc, __file;
|
string __desc, __file;
|
||||||
int __line;
|
int __line;
|
||||||
if (__f._M_get_info(&__desc, &__file, &__line))
|
if (__f._M_get_info(&__desc, &__file, &__line)) [[likely]]
|
||||||
{
|
{
|
||||||
__os.width(4);
|
__os << ' ';
|
||||||
__os << __desc << " at " << __file << ':' << __line;
|
if (__desc.empty()) [[unlikely]]
|
||||||
|
__os << "<unknown>";
|
||||||
|
else
|
||||||
|
__os << __desc;
|
||||||
|
if (!__file.empty()) [[likely]]
|
||||||
|
__os << " at " << __file << ':' << __line;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct _Flag_guard // Set and restore hex format
|
||||||
|
{
|
||||||
|
_Flag_guard(ios& __s) : _M_ios(__s) { }
|
||||||
|
~_Flag_guard() { _M_ios.setf(_M_f); }
|
||||||
|
|
||||||
|
ios& _M_ios;
|
||||||
|
ios::fmtflags _M_f = _M_ios.setf(ios::hex, ios::basefield);
|
||||||
|
};
|
||||||
|
_Flag_guard __g(__os);
|
||||||
|
__os << " [0x" << __f.native_handle() << ']';
|
||||||
return __os;
|
return __os;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -697,7 +716,8 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
|
||||||
inline ostream&
|
inline ostream&
|
||||||
operator<<(ostream& __os, const basic_stacktrace<_Allocator>& __st)
|
operator<<(ostream& __os, const basic_stacktrace<_Allocator>& __st)
|
||||||
{
|
{
|
||||||
for (stacktrace::size_type __i = 0; __i < __st.size(); ++__i)
|
using size_type = typename basic_stacktrace<_Allocator>::size_type;
|
||||||
|
for (size_type __i = 0, __size = __st.size(); __i < __size; ++__i)
|
||||||
{
|
{
|
||||||
__os.width(4);
|
__os.width(4);
|
||||||
__os << __i << "# " << __st[__i] << '\n';
|
__os << __i << "# " << __st[__i] << '\n';
|
||||||
|
|
Loading…
Reference in New Issue