Russian Qt Forum
Ноябрь 23, 2024, 00:56 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1] 2   Вниз
  Печать  
Автор Тема: Отображение реального типа объекта в отладчике  (Прочитано 9406 раз)
enumerator
Гость
« : Июнь 03, 2011, 17:51 »

Доброго времени суток. Интересует такой вопрос. Пусть, например, в программе имеется интерфейс I1  и несколько его реализаций I1Impl1, I1Impl2 и т.д. Разумеется, как правило работа с объектами типов I1ImplX ведется именно через интерфейс I1, т.е. большинство функций принимают на вход ссылку или указатель на I1. При этом существует следующая проблема: фронтенд к отладчику QtCreator по умолчанию не показывает реальный тип объекта, а отображает именно задекларированный тип, т.е. I1, соответственно, внутреннее содержимое объектов не посмотреть, что очень сильно снижает удобство отладки. Существует ли какой-нибудь способ решения этой проблемы, возможно, какой-то "волшебный" инициализирующий скрипт самого gdb, который бы позволил в отладчике QtCreator (или какой-либо другой среды программирования под Linux) видеть реальный тип объекта и его содержимое?
Записан
kambala
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 4747



Просмотр профиля WWW
« Ответ #1 : Июнь 03, 2011, 20:31 »

может в gdb прокатит что-то типа такого?
Код:
po interfaceObject->metaObject()->className()
Записан

Изучением C++ вымощена дорога в Qt.

UTF-8 has been around since 1993 and Unicode 2.0 since 1996; if you have created any 8-bit character content since 1996 in anything other than UTF-8, then I hate you. © Matt Gallagher
enumerator
Гость
« Ответ #2 : Июнь 03, 2011, 21:56 »

даже если такое прокатит, то это не совсем то, чего хочется. Тут есть два недостатка:
1) надо наследоваться от QObject  или определять похожий метод в собственном интерфейсе
2) эту команду нужно набивать руками в консоли gdb для каждого объекта, чего делать не хочется, особенно, если есть
необходимость посмотреть содержимое какого-нибудь контейнера вида std::vector< std::shared_ptr< I1 > >, что возникает достаточно часто.
Самое интересное, что по идее отладчику не должно бы составлять труда реализовать подобную функциональность, учитывая, что всеми необходимыми сведениями он располагает (ведь он видит, куда ведет указатель на таблицу виртуальных функций, а соответственно, точно знает тип объекта), однако ни в одном графическом фронтенде к gdb я такой возможности не видел.
Записан
kamre
Частый гость
***
Offline Offline

Сообщений: 233


Просмотр профиля
« Ответ #3 : Июнь 04, 2011, 20:14 »

Отладчик в QtCreator по сравнению с MSVC какой-то убогий.

Меня тоже раздражает, что для такого кода:
Код:
class Object {
public:
  Object(int id_) : id(id_) {}
  virtual ~Object() {}

private:
  int id;
};

class Point: public Object {
public:
  Point(double x_, double y_, int id_)
    : Object(id_), x(x_), y(y_) {}

private:
  double x, y;
};

class Circle: public Point {
public:
  Circle(double x_, double y_, double r_, int id_)
    : Point(x_, y_, id_), r(r_) {}

private:
  double r;
};

int main()
{
  Object *obj = new Circle(1.5, -2.5, 3.0, 15);
  return 0;  // <== break point here
}

QtCreator показывает только так:


а в MSVC все что нужно показывает:
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #4 : Июнь 04, 2011, 20:22 »

разработчикам гдб зарплату, знаете ли не платят, ога. скажите спасибо что там вообще есть отладчик.

на правах оффтопа - отладчик нужен только стектрейс получать в случае нулл поинтера. те кто лазает по структурам в дебаггере не умеют программировать (иначе откуда у них ошибки в данных)
Записан
kamre
Частый гость
***
Offline Offline

Сообщений: 233


Просмотр профиля
« Ответ #5 : Июнь 04, 2011, 20:34 »

разработчикам гдб зарплату, знаете ли не платят, ога. скажите спасибо что там вообще есть отладчик.

Спасибо!  Смеющийся

на правах оффтопа - отладчик нужен только стектрейс получать в случае нулл поинтера. те кто лазает по структурам в дебаггере не умеют программировать (иначе откуда у них ошибки в данных)
Конечно, если чего-то нет в любимой IDE/Editor/OS, то это просто не нужно. А как только появляется (вроде того же QtCreator с более или менее вменяемым дополнением и навигацией по исходникам), то сразу нахваливать начинают. Известное дело...
Записан
enumerator
Гость
« Ответ #6 : Июнь 04, 2011, 20:36 »

Я когда искал в интернете ответ на этот вопрос, наткнулся на команду самого gdb: set print object on, которая, как я понял, делает как раз то, что нужно, опираясь именно на указатель на таблицу виртуальных функций. С консольным gdb я работать не умею, так что проверить не могу, однако у меня нет поводов не доверять документации gdb. Таким образом получается, что вся проблема в графическом фронтенде к отладчику, а поэтому есть надежда, что в какой-нибудь IDE такая функциональность поддерживается. В Visual Studio и правда отладчик умеет это "из коробки" (вообще, отладчик Visual Studio является ее самым большим плюсом), однако под Linux visual studio нет, а если бы и было, то я бы не стал связываться с ее компилятором (несмотря на все прелести отладчика).
Записан
Sancho_s_rancho
Гость
« Ответ #7 : Июнь 04, 2011, 20:54 »

разработчикам гдб зарплату, знаете ли не платят, ога. скажите спасибо что там вообще есть отладчик.

на правах оффтопа - отладчик нужен только стектрейс получать в случае нулл поинтера. те кто лазает по структурам в дебаггере не умеют программировать (иначе откуда у них ошибки в данных)
Грубовато, но в целом верно. Чем больше программист пользуется отладчиком, тем слабее он представляет, что в его программе на самом деле происходит. Да, все совершают ошибки, но если программа писана не через анус, то достаточно посмотреть код, ну может еще дебажное сообщение вывести.
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #8 : Июнь 04, 2011, 20:54 »


Конечно, если чего-то нет в любимой IDE/Editor/OS, то это просто не нужно. А как только появляется (вроде того же QtCreator с более или менее вменяемым дополнением и навигацией по исходникам), то сразу нахваливать начинают. Известное дело...
Просто магическим образом мой код работает. Я следую принципу - если начинаю путаться в коде, я его выкидываю и ищу более простой вариант. Возможно, я никогда не смогу работать в энтерпрайзе, тк чисто физически не могу писать код не продумав детально и не поставив печать "варианта проще нет".
В примере с картинками - отладчик не должен знать о реальном типе Object, так как о нем не знает сам код. Более того, вы неправильно дебагаете - если у вас пришел объект с битыми данными то искать надо не в том месте, куда он пришел, а в том, где эти данные поломались (сам по себе класс не сломается, скорее всего вы накосячили ещё в процессе создания/инициализации).
Ну и напоследок - какие нафиг проперти у интерфейса? Почему класс с данными использует виртуальное наследование?
Если чего, не хочу никого обидеть, просто ратую чтобы люди думали:) Ну и смотрели примеры правильного/красивого кода.
« Последнее редактирование: Июнь 04, 2011, 20:56 от Авварон » Записан
kamre
Частый гость
***
Offline Offline

Сообщений: 233


Просмотр профиля
« Ответ #9 : Июнь 04, 2011, 20:55 »

Я когда искал в интернете ответ на этот вопрос, наткнулся на команду самого gdb: set print object on, которая, как я понял, делает как раз то, что нужно, опираясь именно на указатель на таблицу виртуальных функций. С консольным gdb я работать не умею, так что проверить не могу, однако у меня нет поводов не доверять документации gdb.
А ведь действительно gdb умеет это показывать:
Цитировать
Reading symbols from D:\Projects\QtCreator\TestDebug-build-desktop\debug/TestDebug.exe...done.
(gdb) break 30
Breakpoint 1 at 0x4013b3: file ..\TestDebug\test.cpp, line 30.
(gdb) run
Starting program: D:\Projects\QtCreator\TestDebug-build-desktop\debug/TestDebug.exe
[New Thread 1784.0x280]

Breakpoint 1, test (obj=0x3e2bf0) at ..\TestDebug\test.cpp:30
30         return 0; // <== break point here
(gdb) print obj
$1 = (Object *) 0x3e2bf0
(gdb) print *obj
$2 = {_vptr.Object = 0x40e260, id = 15}
(gdb) set print object on
(gdb) print obj
$3 = (Circle *) 0x3e2bf0
(gdb) print *obj
$4 = (Circle) {<Point> = {<Object> = {_vptr.Object = 0x40e260, id = 15}, x = 1.5, y = -2.5}, r = 3}
Значит просто QtCreator не умеет этим пользоваться.

В Visual Studio и правда отладчик умеет это "из коробки" (вообще, отладчик Visual Studio является ее самым большим плюсом), однако под Linux visual studio нет, а если бы и было, то я бы не стал связываться с ее компилятором (несмотря на все прелести отладчика).
"Связываться с ее компилятором" намертво и не нужно, если использовать для сборки проекта CMake. Но вести основную разработку (для меня) пока гораздо удобнее в Windows на MSVC, чем в любой IDE в Linux. А потом уже собирать и тестировать отдельно под Linux.
Записан
enumerator
Гость
« Ответ #10 : Июнь 04, 2011, 21:02 »

Интересно, если gdb поддерживает такую фичу, то нельзя ли каким бы то ни был ообразом включить ее при отладке в QtCreator? Вроде как там в настройках предлагают выполнить некий инициализирующий скрипт gdb, возможно, если включение данной опции "вставить" в этот самый скрипт, то QtCreator подхватит нужное поведение.
Записан
Авварон
Джедай : наставник для всех
*******
Offline Offline

Сообщений: 3260


Просмотр профиля
« Ответ #11 : Июнь 04, 2011, 21:05 »

Не на правах оффтопа - если кто-то найдет как это сделать, не поленитесь, сделайте патч к скриптам дебаггинг хелпера и выложите на багтрекере с соответствующей таской или здесь, кто-нибудь создаст таск.
Записан
kamre
Частый гость
***
Offline Offline

Сообщений: 233


Просмотр профиля
« Ответ #12 : Июнь 04, 2011, 21:14 »

Просто магическим образом мой код работает. Я следую принципу - если начинаю путаться в коде, я его выкидываю и ищу более простой вариант. Возможно, я никогда не смогу работать в энтерпрайзе, тк чисто физически не могу писать код не продумав детально и не поставив печать "варианта проще нет".
Да все можно сделать хоть в блокноте, если компилятор уже есть. И если кода не так много, что его легко выбросить и переписать с нуля, то так и нужно делать. А если проект огромный, писался долго и людьми самой разной квалификации? И чтобы провести рефакторинг какого-то куска нужно просить выделить на это время, что очень не охотно делается вышестоящими. Здесь уже любые средства, ускоряющие работу, хороши.

В примере с картинками - отладчик не должен знать о реальном типе Object, так как о нем не знает сам код.
Вот здесь полностью не согласен. Отладчик имеет в наличии всю runtime информацию о ходе работы программы. О реальном типе не знает компилятор во время компиляции.

Более того, вы неправильно дебагаете - если у вас пришел объект с битыми данными то искать надо не в том месте, куда он пришел, а в том, где эти данные поломались (сам по себе класс не сломается, скорее всего вы накосячили ещё в процессе создания/инициализации).
Удобно сразу в отладчике при остановке в этой функции посмотреть на что на самом деле указывает указатель. А данные не обязательно поломались, может быть функция не корректно работает в некоторых случаях.

Ну и напоследок - какие нафиг проперти у интерфейса? Почему класс с данными использует виртуальное наследование?
Если чего, не хочу никого обидеть, просто ратую чтобы люди думали:) Ну и смотрели примеры правильного/красивого кода.
Это просто пример, чтобы было что на скриншоте показать.
Записан
kamre
Частый гость
***
Offline Offline

Сообщений: 233


Просмотр профиля
« Ответ #13 : Июнь 04, 2011, 21:23 »

Вроде как там в настройках предлагают выполнить некий инициализирующий скрипт gdb, возможно, если включение данной опции "вставить" в этот самый скрипт, то QtCreator подхватит нужное поведение.
Не помогает, можно только через Debugger Log посмотреть:


Это я только в .gdbinit записал строку и указал этот файл в настройках Tools->Options...->Debugger->GDB->GDB start up script.
« Последнее редактирование: Июнь 04, 2011, 21:27 от kamre » Записан
enumerator
Гость
« Ответ #14 : Июнь 04, 2011, 21:32 »

Жаль. Интересно, а как же тогда работает фронтенд к отладчику в QtCreator? Ведь насколько я понимаю, он как раз и занимается тем, что шлет команды отладчику и интерпретирует ответ. Каков же тогда его способ получения того содержимого переменных, которое он отображает, неужели в Вашем случае он просто отбросил часть вывода gdb?
Записан
Страниц: [1] 2   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.113 секунд. Запросов: 23.