web-dev-qa-db-ja.com

gdbでは、一部のクラス関数を呼び出すことができますが、「解決できない」ものもあります。どうして?

私はまだ共有ポインタに取り組んでいません..私はコンセプトを知っています。 XMLファイルのデータを格納する次のc ++クラスの関数をデバッグしようとしています( xerces ライブラリを介して読み込みます)。

_// header file
class ParamNode;
typedef boost::shared_ptr<ParamNode> PtrParamNode;

class ParamNode : public boost::enable_shared_from_this<ParamNode> {
public:
   ...
   typedef enum { DEFAULT, EX, PASS, INSERT, APPEND } ActionType;
   bool hasChildren() const;
   PtrParamNode GetChildren();
   PtrParamNode Get(const std::string&  name, ActionType = DEFAULT );
protected:
   ....
   ActionType defaultAction_;
}
_

ここで、クラスへのポインターのインスタンスParamNodeがあり、それが_paramNode__と呼ばれるコードをデバッグしている場合

_PtrParamNode paramNode_;
// read xml file with xerces
paramNode_ = xerces->CreateParamNodeInstance();
// now, the xml data is stored in paramNode_.
std::string probGeo;
// this works in the code, but not in (gdb)!!
paramNode_->Get("domain")->GetValue("gt",probGeo);
cout << probGeo << endl; // <-- breakpoint HERE
_

gdbの使用_paramNode__オブジェクトを検査しています:

_(gdb) p paramNode_
$29 = {px = 0x295df70, pn = {pi_ = 0x2957ac0}}
(gdb) p *paramNode_.px
$30 = {
  <boost::enable_shared_from_this<mainclass::ParamNode>> = {weak_this_ = {px = 0x295df70, pn = {pi_ = 0x2957ac0}}}, 
  _vptr.ParamNode = 0x20d5ad0 <vtable for mainclass::ParamNode+16>, 
  ...
  name_= {...}, 
  children_ = {size_ = 6, capacity_ = 8, data_ = 0x2969798},
  defaultAction_ = mainclass::ParamNode::EX, }
_

そしてそのメンバーを印刷します:

_(gdb) ptype *paramNode_.px
type = class mainclass::ParamNode : public boost::enable_shared_from_this<mainclass::ParamNode> {
  protected:
    ...
    mainclass::ParamNode::ActionType defaultAction_;
  public:
    bool HasChildren(void) const;
    mainclass::PtrParamNode GetChildren(void);
    mainclass::PtrParamNode Get(const std::string &, mainclass::ParamNode::ActionType);
_

ただし、私は関数HasChildrenまたはGetChildrenのみを呼び出すことができますが、Getgdbから呼び出すとエラーが発生します。

_(gdb) p (paramNode_.px)->HasChildren()
 $7 = true
 (gdb) p (paramNode_.px)->GetChildren()
 $8 = (mainclass::ParamNodeList &) @0x295dfb8: {
   size_ = 6, 
   capacity_ = 8, 
   data_ = 0x29697a8
  }
(gdb) p (paramNode_.px)->Get("domain")
 Cannot resolve method mainclass::ParamNode::Get to any overloaded instance
(gdb) set overload-resolution off
(gdb) p (paramNode_.px)->Get("domain")
 One of the arguments you tried to pass to Get could not be converted to what the function wants.
(gdb) p (paramNode_.px)->Get("domain", (paramNode_.px).defaultAction_)
 One of the arguments you tried to pass to Get could not be converted to what the function wants.
_

コードでは、Get("domain")関数を実行しても問題ありません。何故ですか?共有ポインタに関する知識が限られているため、回答に説明を含めていただければありがたいです。

24
Sebastian

gdbはコンパイラではないため、(not-so-)Niceユーザー定義型変換は行われません。 stringを必要とする関数を呼び出す場合は、const char*ではなくstringを指定する必要があります。

残念ながら、gdbはコンパイラではなく、オブジェクトの作成も単純な関数呼び出しではないため、コマンドラインでstd::stringを作成することはできません。

したがって、const char*を受け取り、std::string&を返す小さなヘルパー関数をプログラムに追加する必要があります。ここの参照に注意してください。 gdbはconst参照で結果を渡すことができないため、値で返すことはできません(コンパイラーではありません!)静的オブジェクトへの参照、または割り当てられたオブジェクトへの参照を返すことを選択できます。ヒープ。後者の場合、メモリリークが発生しますが、関数はデバッガからのみ呼び出されることを想定しているため、これは大きな問題ではありません。

std::string& SSS (const char* s)
{
    return *(new std::string(s));
}

その後、gdb

gdb> p (paramNode_.px)->Get(SSS("domain"))

うまくいくはずです。

29

そのような状況で、私はコマンドを与えた後に成功しました

set overload-resolution off
12
rwst

以前の回答にいくつかの追加-

gdbはおそらくこのような変換を行う方法を最終的に学習するでしょう。今はできません。しかし、C++式の構文解析のサポートを改善するための活発な作業があります。

gdbもデフォルトの引数を理解しません。これは一部、gdbのバグです。また、一部はg ++のバグであり、DWARFに放出されません。 DWARFは、自明ではないデフォルトの引数を発行する方法さえ定義していないと思います。

10
Tom Tromey

n.m.の答えは素晴らしいですが、コードを編集して再コンパイルする必要がないようにするには、 GDBでのC++文字列の作成 で与えられた解決策を見てください。

そのソリューションでは、std::stringをヒープ上で初期化し、std::stringは、functionから呼び出したいgdbに渡します。

2
Summers Brennan