根据https://stackoverflow.com/a/11311786/890753中的@EvanED,我创建了一个gdb命令newstr
来创建一个新的std :: string并将其放在一个gdb方便变量中:
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
效果很好:
(gdb) newstr $foo "hello world"
(gdb) p $foo->c_str()
$57 = 0xb22e388 "hello world"
我在其他自定义gdb命令中使用newstr
,所以为了整洁,我还创建了delstr
:
define delstr
call ($arg0)->~basic_string($arg0)
call free($arg0)
set ($arg0)=(void*)0
end
它可以工作,但是析构函数调用会产生一个恼人的消息:
(gdb) delstr $foo
warning: Using non-standard conversion to match method std::string::~basic_string to supplied arguments
$62 = 0
我可以避免“非标准转换”消息吗? (我正在使用gdb 7.10。)
答案 0 :(得分:3)
0
传递给析构函数,而不是$foo
。define delstr
call ($arg0)->~basic_string(0)
# ^
call free($arg0)
set ($arg0)=(void*)0
end
好的,这是怎么回事......我们可以先检查一个析构函数的签名。它确实需要一个整数:
(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);
}
所以&#34;非标准转换&#34;警告是关于将指针转换为整数,这实际上是非标准的。 (警告与析构函数无关。)
但是,出于什么深刻的原因,我们需要首先将一个额外的整数传递给析构函数?事实证明它是... a bug GCC问题(从gcc 6.3.0开始),因为使用clang编译的同一程序(截至文章3.8.1)没有额外的int
参数。
应该知道,在Italium C ++ ABI中,实际上有three destructors(D0, D1, D2)。
GCC有一个optimization -fdeclone-ctor-dtor
,它将三个析构函数的公共部分重构为"D4" destructor。这&#34; D4&#34;析构函数使用an extra argument __in_chrg
来确定D0 / D1 / D2中的哪一个是源,以了解是否调用虚拟基础析构函数。
这&#34; D4&#34;析构函数也以某种方式用作GCC生成的DWARF符号的规范析构函数声明。如果我们检查从GDB错误报告链接的GCC issue,使用&#34; D4&#34;是因为海湾合作委员会的开发商并不想选择D0,D1或D2中的哪一个来祝福。
结果是GDB没有忽略的额外int
。
当析构函数能够完成对象销毁时,__in_chrg
值为2
&#34; (D0,D1)和0
当它只是一个&#34;基础对象析构函数&#34; (D2)。由于std::string
没有虚拟基类,因此您应该将0
传递给该参数。
注意:我使用这个程序来测试GDB:
#include <string>
#include <iostream>
std::string aa;
struct Foo {
Foo() { std::cout << "Constructing: this = " << this << std::endl; }
~Foo() { std::cout << "Destroying: this = " << this << std::endl; }
};
int main() {
Foo foo;
return 0;
}