Вызывающий оператор << в GDB
Как вы звоните operator<<(std::ostream &os, const ClassX &x)
изнутри GDB?
Другими словами, как вы печатаете объект в GDB?
call std::cout<<x
или же call operator<<(std::cout, x)
не похоже на работу для меня!
Есть идеи?
3 ответа
Единственный способ, который я нашел, был таким:
call 'operator<<(std::ostream&, myclass&)'(mycout, c)
поскольку std::cout
GDB по какой-то причине не был виден, мне пришлось прибегнуть к созданию своего собственного так:
std::ostream mycout(std::cout.rdbuf());
Вы не указали причин для этого, но не print yourvariable
быть проще?
Если это абсолютно необходимо, вы могли бы иметь Print
метод в вашем классе и вызвать его из operator<<
а затем позвоните Print
Метод на вашем объекте из GDB.
Обратите внимание, что stdout, вероятно, буферизируется в gdb, поэтому вы не увидите никаких выходных данных, если не перенаправите их как-нибудь.
Смотрите это обсуждение в почтовом архиве GDB по этой проблеме.
Вы также можете определить функцию как:
define printType
call operator<<(std::ostream&, const $arg0 &)(std::cerr, $arg1)
end
И используйте это как:
printType ClassX objectOfClassX
Для меня call operator<<
бежал без ошибок, но не печатал. Оказывается, мне нужно было позвонить flush
, Вот полезная функция, которую вы можете вставить в .gdbinit
:
define str
call (void)operator<<(std::cout, $arg0)
call (void)std::cout.flush()
printf "\n"
end
У меня есть следующее в моем .gdbinit
, Предыдущие ответы здесь не работали для меня, когда operator<<
шаблон или требуется много печатать, чтобы получить правильные типы. Этот подход ищет таблицу символов, чтобы найти правильный operator<<
, Это работает, только если операторы были созданы явно.
python
import gdb
import re
class LexicalCast(gdb.Command):
def __init__(self):
super(LexicalCast, self).__init__("lexical_cast", gdb.COMMAND_DATA)
def matches(self, symbol, type, exact=True):
params = symbol.find('('), symbol.find(')')
if -1 in params: return False
params = symbol[params[0]+1 : params[1]]
if re.match("^%s, %s( const)?&?$"%(re.escape("std::ostream&"), re.escape(type)), params): return True
if not exact and re.match("^%s, .*::%s( const)?&?$"%(re.escape("std::ostream&"), re.escape(type)), params): return True
return False
def invoke(self, arg, from_tty):
value = gdb.parse_and_eval(arg)
type = str(value.type.strip_typedefs().unqualified())
# isn't unqualified() supposed to do that already?
if type.startswith("const "): type = type[6:]
if type.startswith("struct "): type = type[7:]
if type.endswith(" &"): type = type[:-2]
# there's probably a better way to browse the list of symbols ...
shift_operators = gdb.execute("info functions operator<<", False, True).split('\n')
matching_operators = [ op for op in shift_operators if self.matches(op, type)]
if not matching_operators:
gdb.write("No operator<<(std::ostream&, const %s&) found in the symbols. Trying to find a match with additional namespace qualifiers.\n"%(type,))
matching_operators = [ op for op in shift_operators if self.matches(op, type, False)]
if not matching_operators:
gdb.write("No operator<<(std::ostream&, const .*::%s&) found in the symbols. Did you forget to explicitly instantiate your operator?\n"%(type,))
else:
if len(matching_operators) > 1:
gdb.write("Found multiple operator<< matching this expression; trying to call each one of them...\n")
for op in matching_operators:
try:
op = op.split(' ', 1)[1][:-4] if op.endswith("@plt") else op.split(':', 1)[1].split('&', 1)[1].strip()[:-1]
gdb.execute("call (void)'%s'((std::cout), (%s))"%(op, arg))
gdb.execute("call (void)std::cout.put('\\n')")
gdb.execute("call (void)std::cout.flush()")
break
except Exception as e:
gdb.write("Could not invoke %s: %s\n"%(op, e))
LexicalCast()
end
В GDB я использую это так:
(gdb) lex sector[0]
4: 1 ~ ([-3.00170 +/- 3.86e-6], [-1.73303 +/- 7.55e-8])
(gdb) lex 123
No operator<<(std::ostream&, const int&) found in the symbols. Did you explicitly instantiate that operator?
Это, в основном, хак, который, вероятно, сломается, если вы изменили способ печати GDB. info functions
, но это хорошо работает для моих целей.