Подтвердить что ты не робот

В gdb я могу вызвать некоторые функции класса, но другие "не могут быть решены". Зачем?

Я еще не работал над общими указателями. Я просто знаю концепцию. Я пытаюсь отлаживать функции в следующем классе С++, который хранит данные XML файла (чтение через библиотеку 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, тогда как вызов Get из gdb приводит к ошибке:

(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") работает нормально. Почему это? Я благодарен, если вы включили объяснения в свой ответ из-за моего ограниченного знания общих указателей.

4b9b3361

Ответ 1

gdb не является компилятором, он не будет делать (не очень) хорошие пользовательские преобразования типов для вас. Если вы хотите вызвать функцию, которая хочет string, вам нужно дать ей string, а не const char*.

К сожалению, 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"))

должен работать.

Ответ 2

Пара дополнений к предыдущему ответу -

gdb, вероятно, в конечном итоге научится делать такие преобразования. Он не может сейчас; но активная работа по улучшению поддержки синтаксического анализа выражения на С++.

gdb также не понимает аргументы по умолчанию. Это частично ошибка в gdb; но также частично ошибка в g++, которая не выводит их в DWARF. Я думаю, что DWARF даже не определяет способ испускать нетривиальные аргументы по умолчанию.

Ответ 3

В такой ситуации я просто добился успеха после предоставления команды

set overload-resolution off

Ответ 4

N.m. ответ велик, но чтобы избежать необходимости редактировать код и перекомпилировать, взгляните на решение, данное в Создание строки С++ в GDB.

В этом решении они демонстрируют выделение пространства для std::string в куче, а затем инициализацию std::string для перехода в function, которые они хотели бы вызвать из gdb.