печать блиц-массивов через GDB - PullRequest
0 голосов
/ 08 мая 2020

Последние несколько дней я использую пакет массивов Blitz. Во время отладки мне нужно распечатать содержимое массива, а blitz поддерживает что-то вроде ниже

std::cout<<blitz_array_name<<std::endl

Я хотел бы распечатать содержимое массива через GDB во время отладки. Итак, я написал перегруженные функции для разных типов массивов, которые мне нравится печатать, как показано ниже

void printBlitz(blitz::Array<bool, 1> &in)
{
std::cout<<in<<std::endl;
}

void printBlitz(blitz::Array<int, 1> &in)
{
std::cout<<in<<std::endl;
}

... and so on

в отладчике gdb, я могу просто вызвать эту функцию, как показано ниже

(gdb) call printBlitz(blitz_array_name)
  1. Проблема в том, что я использую много разных типов многомерных массивов, мне нужно делать перегрузки для каждого массива
  2. Я не могу вызывать функции шаблона через функцию вызова GDB - это также помогло бы
  3. Я попытался сделать что-то вроде ниже

(gdb) define printmyvar call (void) operator << (std :: cout, $ arg0) print "\ n "end </p>

, когда я пытаюсь распечатать массив, как показано ниже

(gdb) printmyvar blitz_array_name

Я получаю эту ошибку« Невозможно разрешить оператор функции << для любого перегруженного экземпляра »</p>

d ) Я могу определить макрос, как показано ниже

   PRINTBLITZ(myvar) std::cout<<myvar<<std::endl

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

Как мы можем просто выполнить что-то подобное ниже из GDB

std::cout<<myvar<<std::endl

Пожалуйста, предложите любое решение для этой проблемы. Любое предложение приветствуется и ускоряет мою отладку.

Большое спасибо заранее !!

1 Ответ

1 голос
/ 08 мая 2020
Я не могу вызывать функции шаблона через функцию вызова GDB - это тоже поможет.

На самом деле, после нескольких попыток кажется, что можно, но трудно расставить точки это правильно.

Рассмотрим следующий код

#include <iostream>

double tripleInput(double x) { return 3 * x; }

template <typename T>
inline T doubleInput(T x) {
    return 2 * x;
}


int main(int argc, char *argv[])
{
    std::cout << doubleInput(13) << std::endl;
    std::cout << doubleInput(1.72) << std::endl;

    std::cout << tripleInput(1.72) << std::endl;
    return 0;
}

После компиляции с отладочными символами и запуска gdb с исполняемым файлом мы можем сделать

call tripleInput(1.5)

, и gdb вернет 4.5 . Все идет нормально. Однако обратите внимание, что если вы напишете call tri и нажмете TAB, gdb завершит имя как tripleInput(double). После этого вы добавляете (1.5) и можете запускать как

tripleInput(double)(1.5)

, который будет работать, как и раньше.

Теперь давайте попробуем использовать шаблонную функцию doubleInput. Это имя шаблона, но только после того, как вы используете шаблон с некоторым типом, компилятор сгенерирует функцию из шаблона. Фактические имена: doubleInput<int>, doubleInput<double>, и c. Только версии , которые вы фактически использовали , будут в двоичном файле и могут быть просмотрены gdb.

Теперь давайте попробуем

call doubleInput<double>(1.7)

, и gdb вернет 3.3999999999999999. Большой! Обратите внимание, что

call doubleInput<double>(double)(1.7)

также работает. Просто помните, что

call doubleInput<int>(1.7)

возвращает 2 вместо 3,3999999999999999, но это имеет смысл.

Итак, ответ состоит в том, что вы можете вызывать экземпляры шаблона, если вы передаете полное имя (используйте TAB для завершения имени).

Просто последнее замечание, если я изменю tripleInput и doubleInput для получения аргумента по ссылке, а не по значению, тогда это не сработает, и я получу ошибка «Попытка взять адрес значения, не находящегося в памяти».


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

С предыдущим ответом это означает, что вы можете написать один шаблон вместо нескольких реализаций. Только не забудьте позвонить один раз. Даже если вы реализуете несколько функций, вам все равно нужно вызывать их, чтобы компоновщик не удалял их из двоичного файла.


Но для облегчения отладки лучшее решение, безусловно, использует API Python gdb для написания собственных симпатичных принтеров для типов bliz::Array. Если бы у вас были симпатичные принтеры для блиц-шрифтов и все, что вам нужно, чтобы увидеть blitz::Array, было p variable_name. Это всегда будет работать, даже если вы отлаживаете из основного файла (без неполноценного запуска вы не можете вызвать функцию).

К сожалению, я не смог найти ни одной существующей реализации хороших принтеров для блиц, что означает что вам придется написать это самостоятельно.

У меня нет опыта работы с блицем, но я часто использую armadillo , библиотеку C ++ для линейной алгебры и научных вычислений c , и я написал красивые принтеры для броненосцев. См. этот ответ и этот репозиторий , если вам любопытно.

Чтобы написать красивые принтеры, вы должны немного понимать, как тип, для которого вы пишете красивые принтеры хранит свои данные. Вам нужно будет прочитать об этом документацию gdb , но лучше всего посмотреть другие реализации симпатичных принтеров. По крайней мере, так я и сделал.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...