I forgot to comment on the chosen behavior of _GLIBCXX_DEBUG_BACKTRACE.
So, if the user define it, it means that he has install libbacktrace on
its system. However we silently ignore it if libbacktrace is eventually
not supported. I think it is the simplest thing to do. I am not
convinced by the #warning. Personnaly I always try to build without any
warnings and most of the time I consider warnings as errors.
Regarding the post-treatment I introduced here is an example of
transformation.
BEFORE:
/home/fdt/dev/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/debug/vector:606:
In function:
std::__debug::vector<_Tp, _Allocator>::iterator
std::__debug::vector<_Tp,
_Allocator>::insert(std::__debug::vector<_Tp,
_Allocator>::const_iterator, _InputIterator, _InputIterator) [with
_InputIterator =
std::move_iterator<__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<std::unique_ptr<int>*,
std::__cxx1998::vector<std::unique_ptr<int>,
std::allocator<std::unique_ptr<int> > > >,
std::__debug::vector<std::unique_ptr<int> >,
std::random_access_iterator_tag> >; <template-parameter-2-2> =
void; _Tp
= std::unique_ptr<int>; _Allocator =
std::allocator<std::unique_ptr<int>
>; std::__debug::vector<_Tp, _Allocator>::iterator =
__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<std::unique_ptr<int>*,
std::__cxx1998::vector<std::unique_ptr<int>,
std::allocator<std::unique_ptr<int> > > >,
std::__debug::vector<std::unique_ptr<int> >,
std::random_access_iterator_tag>; typename
std::iterator_traits<typename
std::__cxx1998::vector<_Tp, _Alloc>::iterator>::iterator_category =
std::random_access_iterator_tag; typename std::__cxx1998::vector<_Tp,
_Alloc>::iterator =
__gnu_cxx::__normal_iterator<std::unique_ptr<int>*,
std::__cxx1998::vector<std::unique_ptr<int>,
std::allocator<std::unique_ptr<int> > > >; std::__debug::vector<_Tp,
_Allocator>::const_iterator =
__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<const
std::unique_ptr<int>*, std::__cxx1998::vector<std::unique_ptr<int>,
std::allocator<std::unique_ptr<int> > > >,
std::__debug::vector<std::unique_ptr<int> >,
std::random_access_iterator_tag>; typename
std::iterator_traits<typename
std::__cxx1998::vector<_Tp,
_Alloc>::const_iterator>::iterator_category
= std::random_access_iterator_tag; typename
std::__cxx1998::vector<_Tp,
_Alloc>::const_iterator = __gnu_cxx::__normal_iterator<const
std::unique_ptr<int>*, std::__cxx1998::vector<std::unique_ptr<int>,
std::allocator<std::unique_ptr<int> > > >]
Backtrace:
0x4029ff
__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<std::unique_ptr<int,
std::default_delete<int> >*, std::__cxx1998::vector<std::unique_ptr<int,
std::default_delete<int> >, std::allocator<std::unique_ptr<int,
std::default_delete<int> > > > >,
std::__debug::vector<std::unique_ptr<int, std::default_delete<int> >,
std::allocator<std::unique_ptr<int, std::default_delete<int> > > >,
std::random_access_iterator_tag>
std::__debug::vector<std::unique_ptr<int, std::default_delete<int> >,
std::allocator<std::unique_ptr<int, std::default_delete<int> > >
>::insert<std::move_iterator<__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<std::unique_ptr<int, std::default_delete<int> >*, std::__cxx1998::vector<std::unique_ptr<int, std::default_delete<int> >, std::allocator<std::unique_ptr<int, std::default_delete<int> > > > >, std::__debug::vector<std::unique_ptr<int, std::default_delete<int> >, std::allocator<std::unique_ptr<int, std::default_delete<int> > > >, std::random_access_iterator_tag> >, void>(__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<std::unique_ptr<int, std::default_delete<int> > const*, std::__cxx1998::vector<std::unique_ptr<int, std::default_delete<int> >, std::allocator<std::unique_ptr<int, std::default_delete<int> > > > >, std::__debug::vector<std::unique_ptr<int, std::default_delete<int> >, std::allocator<std::unique_ptr<int, std::default_delete<int> > > >, std::random_access_iterator_tag>, std::move_iterator<__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<std::unique_ptr<int, std::default_delete<int> >*, std::__cxx1998::vector<std::unique_ptr<int, std::default_delete<int> >, std::allocator<std::unique_ptr<int, std::default_delete<int> > > > >, std::__debug::vector<std::unique_ptr<int, std::default_delete<int> >, std::allocator<std::unique_ptr<int, std::default_delete<int> > > >, std::random_access_iterator_tag> >, std::move_iterator<__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<std::unique_ptr<int, std::default_delete<int> >*, std::__cxx1998::vector<std::unique_ptr<int, std::default_delete<int> >, std::allocator<std::unique_ptr<int, std::default_delete<int> > > > >, std::__debug::vector<std::unique_ptr<int, std::default_delete<int> >, std::allocator<std::unique_ptr<int, std::default_delete<int> > > >, std::random_access_iterator_tag> >)
/home/fdt/dev/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/debug/vector:606
0x4030cc test01()
/home/fdt/dev/gcc/git/libstdc++-v3/testsuite/23_containers/vector/debug/insert7_neg.cc:34
0x401458 main
/home/fdt/dev/gcc/git/libstdc++-v3/testsuite/23_containers/vector/debug/insert7_neg.cc:42
Error: attempt to insert with an iterator range [__first, __last) from this
container.
Objects involved in the operation:
iterator "__first" @ 0x0x7ffd719fc0f0 {
type =
std::move_iterator<__gnu_cxx::__normal_iterator<std::unique_ptr<int,
std::default_delete<int> >*, std::__cxx1998::vector<std::unique_ptr<int,
std::default_delete<int> >, std::allocator<std::unique_ptr<int,
std::default_delete<int> > > > > > (mutable iterator);
state = dereferenceable (start-of-sequence);
references sequence with type
'std::__debug::vector<std::unique_ptr<int, std::default_delete<int> >,
std::allocator<std::unique_ptr<int, std::default_delete<int> > > >' @
0x0x7ffd719fc4d0
}
iterator "__last" @ 0x0x7ffd719fc0f0 {
type =
std::move_iterator<__gnu_cxx::__normal_iterator<std::unique_ptr<int,
std::default_delete<int> >*, std::__cxx1998::vector<std::unique_ptr<int,
std::default_delete<int> >, std::allocator<std::unique_ptr<int,
std::default_delete<int> > > > > > (mutable iterator);
state = past-the-end;
references sequence with type
'std::__debug::vector<std::unique_ptr<int, std::default_delete<int> >,
std::allocator<std::unique_ptr<int, std::default_delete<int> > > >' @
0x0x7ffd719fc4d0
}
sequence "this" @ 0x0x7ffd719fc4d0 {
type = std::__debug::vector<std::unique_ptr<int,
std::default_delete<int> >, std::allocator<std::unique_ptr<int,
std::default_delete<int> > > >;
}
XFAIL: 23_containers/vector/debug/insert7_neg.cc execution test
AFTER:
/home/fdt/dev/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/debug/vector:606:
In function:
std::__debug::vector<_Tp, _Allocator>::iterator
std::__debug::vector<_Tp,
_Allocator>::insert(std::__debug::vector<_Tp,
_Allocator>::const_iterator, _InputIterator, _InputIterator) [with
_InputIterator =
std::move_iterator<__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<std::unique_ptr<int>*,
std::vector<std::unique_ptr<int>> >,
std::__debug::vector<std::unique_ptr<int> >,
std::random_access_iterator_tag> >; <template-parameter-2-2> =
void; _Tp
= std::unique_ptr<int>; _Allocator =
std::allocator<std::unique_ptr<int>
>; std::__debug::vector<_Tp, _Allocator>::iterator =
__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<std::unique_ptr<int>*,
std::vector<std::unique_ptr<int>> >,
std::__debug::vector<std::unique_ptr<int> >,
std::random_access_iterator_tag>; typename
std::iterator_traits<typename
std::vector<_Tp, _Alloc>::iterator>::iterator_category =
std::random_access_iterator_tag; typename std::vector<_Tp,
_Alloc>::iterator =
__gnu_cxx::__normal_iterator<std::unique_ptr<int>*,
std::vector<std::unique_ptr<int>> >; std::__debug::vector<_Tp,
_Allocator>::const_iterator =
__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<const
std::unique_ptr<int>*, std::vector<std::unique_ptr<int>> >,
std::__debug::vector<std::unique_ptr<int> >,
std::random_access_iterator_tag>; typename
std::iterator_traits<typename
std::vector<_Tp, _Alloc>::const_iterator>::iterator_category =
std::random_access_iterator_tag; typename std::vector<_Tp,
_Alloc>::const_iterator = __gnu_cxx::__normal_iterator<const
std::unique_ptr<int>*, std::vector<std::unique_ptr<int>> >]
Backtrace:
0x4029ff
__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<std::unique_ptr<int,
std::default_delete<int> >*, std::vector<std::unique_ptr<int,
std::default_delete<int> >> >> std::__debug::vector<std::unique_ptr<int,
std::default_delete<int>
>>::insert<std::move_iterator<__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<std::unique_ptr<int, std::default_delete<int> >*, std::vector<std::unique_ptr<int, std::default_delete<int> >> >> >, void>(__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<std::unique_ptr<int, std::default_delete<int> > const*, std::vector<std::unique_ptr<int, std::default_delete<int> >> >>, std::move_iterator<__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<std::unique_ptr<int, std::default_delete<int> >*, std::vector<std::unique_ptr<int, std::default_delete<int> >> >> >, std::move_iterator<__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<std::unique_ptr<int, std::default_delete<int> >*, std::vector<std::unique_ptr<int, std::default_delete<int> >> >> >)
/home/fdt/dev/gcc/build/x86_64-pc-linux-gnu/libstdc++-v3/include/debug/vector:606
0x4030cc test01()
/home/fdt/dev/gcc/git/libstdc++-v3/testsuite/23_containers/vector/debug/insert7_neg.cc:34
0x401458 main
/home/fdt/dev/gcc/git/libstdc++-v3/testsuite/23_containers/vector/debug/insert7_neg.cc:42
Error: attempt to insert with an iterator range [__first, __last) from this
container.
Objects involved in the operation:
iterator "__first" @ 0x0x7fffdbf5ea10 {
type =
std::move_iterator<__gnu_cxx::__normal_iterator<std::unique_ptr<int,
std::default_delete<int> >*, std::vector<std::unique_ptr<int,
std::default_delete<int> >> > > (mutable iterator);
state = dereferenceable (start-of-sequence);
references sequence with type
'std::__debug::vector<std::unique_ptr<int, std::default_delete<int> >>'
@ 0x0x7fffdbf5edf0
}
iterator "__last" @ 0x0x7fffdbf5ea10 {
type =
std::move_iterator<__gnu_cxx::__normal_iterator<std::unique_ptr<int,
std::default_delete<int> >*, std::vector<std::unique_ptr<int,
std::default_delete<int> >> > > (mutable iterator);
state = past-the-end;
references sequence with type
'std::__debug::vector<std::unique_ptr<int, std::default_delete<int> >>'
@ 0x0x7fffdbf5edf0
}
sequence "this" @ 0x0x7fffdbf5edf0 {
type = std::__debug::vector<std::unique_ptr<int,
std::default_delete<int> >>;
}
XFAIL: 23_containers/vector/debug/insert7_neg.cc execution test
It is just better, not ideal of course. And you are right, current code
can fail to do the proper thing.
I am clearly not the first one to try such a thing and to struggle to do
so. So just tell me if you prefer I keep the original labels and I'll do so.
François
On 6/6/19 11:43 PM, Jonathan Wakely wrote:
On 06/06/19 22:33 +0200, François Dumont wrote:
Here is what I come up with.
Regarding allocation in print_function I would also prefer to avoid
it. But this patch also aim at creating a backtrace_state object in
case of UB so the alloc is perhaps not so important. I can't use
string_view as I need to modify it to display only a part of it
I was only referring to these strings, which allocated memory on every
call to print_function, but you don't modify:
+ const string cxx1998 = "__cxx1998::";
+ const string allocator = ", std::allocator<";
+ const string safe_iterator = "__gnu_debug::_Safe_iterator<";
I see you've changed them now though.
through fsprintf. I could try to use "%.*s" however. I haven't also
consider your remark about template parameters containing '<' yet.
+#if defined(_GLIBCXX_DEBUG_BACKTRACE)
+# if !defined(BACKTRACE_SUPPORTED)
+# if defined(__has_include) &&
!__has_include(<backtrace-supported.h>)
+# error No libbacktrace backtrace-supported.h file found.
+# endif
+# include <backtrace-supported.h>
+# endif
+# if !BACKTRACE_SUPPORTED
+# error libbacktrace not supported.
+# endif
+# include <backtrace.h>
+#else
+# include <stdint.h> // For uintptr_t.
Please use <cstdint> and std::uintptr_t.
I did so but then realized that to do so I had to be in C++11 mode. I
used tr1/cstdint in pre-C++11 mode.
Ugh, right, of course, sorry.
Then I guess <stdint.h> is better than relying on TR1 (even though
<stdint.h> isn't technically part of C++98 either).