在gdb中调用std::~BASIC_STRING [英] Calling std::~basic_string() in gdb

查看:20
本文介绍了在gdb中调用std::~BASIC_STRING的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

按照https://stackoverflow.com/a/11311786/890753中的@Evaned,我创建了一个gdb命令newstr来创建一个新的std::字符串并将其放入一个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。)

推荐答案

TL;DR:将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);
}

因此,"非标准转换"警告是关于将指针转换为整数,这确实是非标准的。(该警告与析构函数无关。)

但是,出于什么深刻的原因,我们首先需要将一个额外的整数传递给析构函数?原来是…a bug😃A GCC问题(截至GCC 6.3.0)实际上,因为使用clang编译的同一程序(截至clang 3.8.1)没有额外的int参数。


应该知道,在意大利的C++ABI中,实际上有three destructors(D0, D1, D2)。

GCC有一个optimization -fdeclone-ctor-dtor,它将三个析构函数的公共部分重新分解为一个"D4" destructor。此"D4"析构函数使用an extra argument __in_chrg来确定D0/d1/D2中的哪一个是源,以了解是否调用虚拟基析构函数。

这个"D4"析构函数不知何故也被用作GCC生成的侏儒符号的规范析构函数声明。如果我们查看GDB错误报告中链接的GCC issue,使用D4的原因是GCC开发人员不想选择D0、D1或D2中的哪一个来祝福。

结果是gdb没有忽略的额外int

当析构函数能够"完全销毁对象"(D0,d1)时,__in_chrg值是2,当它只是一个"基本对象析构函数"(D2)时,0值是0。由于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;
}

这篇关于在gdb中调用std::~BASIC_STRING的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆