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).




Reply via email to