Таким образом, мое решение - загрузить общий объект, содержащий мои процедуры отладки, во время выполнения, используя dlopen. Оказывается, это даже проще, чем я думал, когда вы правильно настроили все флаги компиляции.
В OS X это означает, что вы компилируете свое приложение и отлаживаете объект следующим образом:
all : application.x debug_helper.so
application.x : application.cpp
g++ -g application.cpp -o application.x -fPIC
debug_helper.so : debug_helper.o
g++ -dynamiclib -o debug_helper.so debug_helper.o
debug_helper.o : debug_helper.cpp
g++ -Wall -g -fPIC -c debug_helper.cpp
Критически важен параметр -fPIC для приложения, как и -dynamiclib (вместо попытки использовать флаг linux -shared)
Пример файла debug_helper.cpp может выглядеть следующим образом
#include <map>
#include <stdio.h>
extern "C"
void printMap( const std::map<int,int> &m )
{
printf("Map of size %d\n", int(m.size()) );
for( std::map<int,int>::const_iterator it = m.begin(); it!=m.end(); ++it )
{
printf("%d : %d \n", it->first, it->second );
}
fflush(stdout);
}
Не знаю, почему я решил использовать stdio, а не iostream ... Думаю, вы можете использовать и то, и другое. (только не забудьте смыть потоки ...)
Теперь файл моего приложения выглядит так:
#include <map>
int main()
{
std::map<int,int> m;
m[1]=2;
m[2]=5;
m[3]=10;
m[4]=17;
}
И вот пример сеанса отладки (некоторые выходные данные удалены)
Запустите приложение и разбейте на интересный момент
(gdb) break main
(gdb) run
Reading symbols for shared libraries +++. done
Breakpoint 1, main () at test.cpp:5
5 std::map<int,int> m;
Загрузка в библиотеку помощника по отладке
(gdb) print (void*) dlopen("debug_helper.so",2)
Reading symbols for shared libraries . done
$1 = (void *) 0x100270
(gdb) n
6 m[1]=2;
GDB умен и ловит все новые символы для нас, поэтому нам не нужно использовать dlsym и т. Д.
Мы можем просто вызвать функции напрямую.
(gdb) call printMap(m)
Map of size 0
(gdb) n
(gdb) n
(gdb) n
9 m[4]=17;
(gdb) call printMap(m)
Map of size 3
1 : 2
2 : 5
3 : 10
Давайте добавим больше информации в printMap.
Сначала выгрузите библиотеку.
(gdb) print (int) dlclose($1)
$2 = 0
Редактировать источник, чтобы добавить в сумму записей. Перекомпилируйте и затем загрузите
новая библиотека обратно в GDB (без перезапуска исполняемого файла или GDB)
(gdb) print (void*) dlopen("debug_helper.so",2)
Reading symbols for shared libraries . done
Использовать модифицированную функцию
$3 = (void *) 0x100270
(gdb) call printMap(m)
Map of size 3
1 : 2
2 : 5
3 : 10
SUM = 17
Я думаю, что это делает все, что мне нужно.