Calling std::~basic_string() in gdb

2019-05-22 23:25发布

问题:

As per @EvanED in https://stackoverflow.com/a/11311786/890753 I created a gdb command newstr to create a new std::string and put it in a gdb convenience variable:

define newstr
set ($arg0)=(std::string*)malloc(sizeof(std::string))
call ($arg0)->basic_string()
# 'assign' returns *this; casting return to void avoids printing of the struct.
call (void)( ($arg0)->assign($arg1) )
end

It works great:

(gdb) newstr $foo "hello world"
(gdb) p $foo->c_str()
$57 = 0xb22e388 "hello world"

I use newstr in other custom gdb commands, so for tidyness I also created delstr:

define delstr
call ($arg0)->~basic_string($arg0)
call free($arg0)
set ($arg0)=(void*)0
end

It works, but the destructor call produces an annoying message:

(gdb) delstr $foo
warning: Using non-standard conversion to match method std::string::~basic_string to supplied arguments
$62 = 0

Can I avoid the "non-standard conversion" message? (I'm using gdb 7.10.)

回答1:

TL;DR: Pass 0 to the destructor, instead of $foo.

define delstr
call ($arg0)->~basic_string(0)
#                           ^
call free($arg0)
set ($arg0)=(void*)0
end

OK so what is going on... We can first check the signature of a destructor. It indeed takes an integer:

(gdb) p ((Foo*) 0)->~Foo
$1 = {void (Foo * const, int)} 0x555555554c00 <Foo::~Foo()>

(gdb) p (('std::__cxx11::string'*) 0)->~basic_string
$2 = {void (std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > * const, int)} 0x7ffff7b75010 <std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >::~basic_string()>

(gdb) ptype Foo
type = struct Foo {
  public:
    Foo(void);
    ~Foo(int);
}

So the "non-standard conversion" warning is about converting a pointer to an integer, which is indeed non-standard. (The warning has nothing to do with the destructor.)

But for what profound reason do we need to pass an extra integer to the destructor in the first place? Turns out it is … a bug