A user pointed out that, in DAP mode, gdb would hang while trying to
display a certain vector. See
https://sourceware.org/bugzilla/show_bug.cgi?id=33594
This is caused by a combination of things: the vector is
uninitialized, DAP requires a count of the number of children of a
variable, and libstdc++ printers don't implement the 'num_children'
method, so gdb tries to count children by iterating.
In this case, the vector has a nonsensical size:
(gdb) p myVector
$1 = std::vector of length -34979931, capacity -33992726
This patch adds a 'num_children' method to a subset of the
pretty-printers, in particular ones where I thought the length might
be arbitrarily large and susceptible to being garbage when the object
isn't initialized.
I've also specifically added a check to the vector printer for the
case where the length is negative.
These container printers could be further improved by adding the
'child' method, allowing random access to child objects. However I
haven't done that here.
libstc++-v3/ChangeLog
* python/libstdcxx/v6/printers.py (StdVectorPrinter._bounds):
New method.
(StdVectorPrinter.to_string): Use it.
(StdVectorPrinter.num_children): New method.
(StdStackOrQueuePrinter.num_children): New method.
(StdMapPrinter.num_children): New method.
(StdSetPrinter.num_children): New method.
(StdDequePrinter._size): New method.
(StdDequePrinter.to_string): Use it.
(StdDequePrinter.num_children): New method.
(Tr1UnorderedSetPrinter.num_children): New method.
(Tr1UnorderedMapPrinter.num_children): New method.
(StdSpanPrinter.num_children): New method.
---
libstdc++-v3/python/libstdcxx/v6/printers.py | 62 ++++++++++++++++----
1 file changed, 52 insertions(+), 10 deletions(-)
diff --git a/libstdc++-v3/python/libstdcxx/v6/printers.py
b/libstdc++-v3/python/libstdcxx/v6/printers.py
index 7a5a627479f..f7f0489abf9 100644
--- a/libstdc++-v3/python/libstdcxx/v6/printers.py
+++ b/libstdc++-v3/python/libstdcxx/v6/printers.py
@@ -572,7 +572,10 @@ class StdVectorPrinter(printer_base):
self._val['_M_impl']['_M_finish'],
self._is_bool)
- def to_string(self):
+ # Helper to compute the bounds of the vector.
+ # Returns a tuple: (length, capacity, suffix)
+ # SUFFIX is a type-name suffix to print.
+ def _bounds(self):
start = self._val['_M_impl']['_M_start']
finish = self._val['_M_impl']['_M_finish']
end = self._val['_M_impl']['_M_end_of_storage']
@@ -582,13 +585,27 @@ class StdVectorPrinter(printer_base):
fo = self._val['_M_impl']['_M_finish']['_M_offset']
itype = start.dereference().type
bl = 8 * itype.sizeof
- length = bl * (finish - start) + fo
- capacity = bl * (end - start)
- return ('%s<bool> of length %d, capacity %d'
- % (self._typename, int(length), int(capacity)))
+ length = int(bl * (finish - start) + fo)
+ capacity = int(bl * (end - start))
+ suffix = '<bool>'
else:
- return ('%s of length %d, capacity %d'
- % (self._typename, int(finish - start), int(end - start)))
+ length = int(finish - start)
+ capacity = int(end - start)
+ suffix = ''
+ if length < 0:
+ # Probably uninitialized.
+ length = 0
+ capacity = 0
+ return (length, capacity, suffix)
+
+ def to_string(self):
+ (length, capacity, suffix) = self._bounds()
+ return ('%s%s of length %d, capacity %d'
+ % (self._typename, suffix, length, capacity))
+
+ def num_children(self):
+ (length, capacity, suffix) = self._bounds()
+ return length
def display_hint(self):
return 'array'
@@ -733,6 +750,11 @@ class StdStackOrQueuePrinter(printer_base):
return '%s wrapping: %s' % (self._typename,
self._visualizer.to_string())
+ def num_children(self):
+ if hasattr(self._visualizer, 'num_children'):
+ return self._visualizer.num_children()
+ return None
+
def display_hint(self):
if hasattr(self._visualizer, 'display_hint'):
return self._visualizer.display_hint()
@@ -876,6 +898,9 @@ class StdMapPrinter(printer_base):
node = lookup_node_type('_Rb_tree_node', self._val.type).pointer()
return self._iter(RbtreeIterator(self._val), node)
+ def num_children(slf):
+ return len(RbtreeIterator(self._val))
+
def display_hint(self):
return 'map'
@@ -915,6 +940,8 @@ class StdSetPrinter(printer_base):
node = lookup_node_type('_Rb_tree_node', self._val.type).pointer()
return self._iter(RbtreeIterator(self._val), node)
+ def num_children(slf):
+ return len(RbtreeIterator(self._val))
class StdBitsetPrinter(printer_base):
"""Print a std::bitset."""
@@ -1006,7 +1033,8 @@ class StdDequePrinter(printer_base):
else:
self._buffer_size = 1
- def to_string(self):
+ # Helper to compute the size.
+ def _size(self):
start = self._val['_M_impl']['_M_start']
end = self._val['_M_impl']['_M_finish']
@@ -1014,9 +1042,11 @@ class StdDequePrinter(printer_base):
delta_s = start['_M_last'] - start['_M_cur']
delta_e = end['_M_cur'] - end['_M_first']
- size = self._buffer_size * delta_n + delta_s + delta_e
+ return long(self._buffer_size * delta_n + delta_s + delta_e)
- return '%s with %s' % (self._typename, num_elements(long(size)))
+ def to_string(self):
+ size = self._size()
+ return '%s with %s' % (self._typename, num_elements(size))
def children(self):
start = self._val['_M_impl']['_M_start']
@@ -1024,6 +1054,9 @@ class StdDequePrinter(printer_base):
return self._iter(start['_M_node'], start['_M_cur'], start['_M_last'],
end['_M_cur'], self._buffer_size)
+ def num_children(self):
+ return self._size()
+
def display_hint(self):
return 'array'
@@ -1210,6 +1243,9 @@ class Tr1UnorderedSetPrinter(printer_base):
return izip(counter, Tr1HashtableIterator(self._hashtable()))
return izip(counter, StdHashtableIterator(self._hashtable()))
+ def num_children(self):
+ return int(self._hashtable()['_M_element_count'])
+
class Tr1UnorderedMapPrinter(printer_base):
"""Print a std::unordered_map or tr1::unordered_map."""
@@ -1254,6 +1290,9 @@ class Tr1UnorderedMapPrinter(printer_base):
# Zip the two iterators together.
return izip(counter, data)
+ def num_children(self):
+ return int(self._hashtable()['_M_element_count'])
+
def display_hint(self):
return 'map'
@@ -1949,6 +1988,9 @@ class StdSpanPrinter(printer_base):
def children(self):
return self._iterator(self._val['_M_ptr'], self._size)
+ def num_children(self):
+ return int(self._size)
+
def display_hint(self):
return 'array'
--
2.51.0