( Почему при отладке некоторые поля "отсутствуют"? (c#) выглядит аналогично, но это не так)
Контекст
У меня есть переменная Nlohmann JSON simple_json
и отлаживаемая программа, включены символы отладки. Я хочу исследовать память и наблюдать смещения полей.
Я могу получить адрес в GDB:
(gdb) p &(*simple_json.m_value.object)
(nlohmann::basic_json<std::map, <lots of stuff removed>, nlohmann::adl_serializer>::object_t *) 0x174d20
Точно так же, у меня могут быть другие адреса:
(gdb) p &(*simple_json.m_value.object)._M_t
(gdb) p &(*simple_json.m_value.object)._M_t._M_impl
# both gives same value. This is due to how C++ STL are made.
# perfectly normal
# (obviously not the same type, all GDB outputs truncated for sake of readability)
(... redacted ...) 0x174d20
(gdb) p &(*simple_json.m_value.object)._M_t._M_impl._M_header
(std::_Rb_tree_node_base *) 0x174d28
# left node
(gdb) p &(*simple_json.m_value.object)._M_t._M_impl._M_header._M_left
(std::_Rb_tree_node_base::_Base_ptr *) 0x174d38
Проблема
Итак, на моей платформе есть разница 0x8 (8) между simple_json.m_value.object._M_t._M_impl
и simple_json.m_value.object)._M_t._M_impl._M_header
Fine.
Но когда я прошу GDB напечатать структуры для _M_impl
нет никакой подсказки, что:
- имеет поле
_M_header
_M_header
поле имеет известное смещение
См. (Победа 64b):
(gdb) ptype /o (*simple_json.m_value.object)._M_t._M_impl
/* offset | size */ type = struct std::_Rb_tree< ... redacted...> {
/* total size (bytes): 48 */
}
Однако ptype, похоже, работает на другой платформе (здесь raspi 3+ 32b; точно такой же код + параметры компиляции):
(gdb) ptype /o (*simple_json.m_value.object)._M_t._M_impl
/* offset | size */ type = struct std::_Rb_tree< ... redacted ... > {
public:
/* 0 | 1 */ _Key_compare _M_key_compare;
/* XXX 3-byte hole */
/* 4 | 16 */ struct std::_Rb_tree_node_base {
/* 4 | 4 */ std::_Rb_tree_color _M_color;
/* 8 | 4 */ _Base_ptr _M_parent;
/* 12 | 4 */ _Base_ptr _M_left;
/* 16 | 4 */ _Base_ptr _M_right;
/* total size (bytes): 16 */
} _M_header;
/* 20 | 4 */ size_type _M_node_count;
/* total size (bytes): 24 */
}
Не нашел подсказки по проблемам GDB база данных: https://sourceware.org/bugzilla/buglist.cgi?quicksearch=ptype
Вопрос
- Почему GDB не может отображать поля
_M_impl
на некоторых платформах? - Могу ли я что-нибудь сделать для одинакового поведения GDB на разных платформах?
С такими же параметрами оптимизации (здесь -o0
mea я думал, что разные платформы будут давать одинаковые результаты.
Чего мне не хватает? Это как-то связано с 1800+ строками #if ... #define
из https://github.com/nlohmann/json/blob/develop/single_include/nlohmann/json.hpp?
Я знаю, что есть python GDB принтер pahole
, который мог бы дать мне больше информации, но это не главное для моего вопроса (я хочу знать «почему?», а не «как я могу жить без?»)
MCVE / Версии инструментов
Набор инструментов для компиляции:
- Выигрыш:
GNAT Community 2019 (20190517-83)
- Распи:
GNAT 6.3.0
GDB версии:
- победа:
GNU gdb (GDB) 8.3 for GNAT Community 2019 [rev=gdb-8.3-ref-194-g3fc1095]
- распи:
GNU gdb (GDB) 8.3.1
MCVE (main. cpp, используется json .h от nlohmann json repo):
#include "json.hpp"
#include <iostream>
using json = nlohmann::json;
int main() {
json simple_json;
simple_json["some_key"] = "any_value_you_like";
std::cout << " a console print" << std::endl; // <-- breakpoint here
return 0;
}
Параметры компиляции / ссылки (файл проекта GPR):
project my_project is
for Source_Dirs use ("src", "include");
for Object_Dir use "obj";
for Exec_Dir use "exe";
for Main use ("main.cpp");
for Languages use ("C++");
package Naming is
for Spec_Suffix ("C++") use ".hpp";
for Body_Suffix ("C++") use ".cpp";
end Naming;
package Compiler is
-- no optims for ease of debug breakpoints; keep debug symbols
for Switches ("C++") use ("-O0", "-Wall", "-Woverloaded-virtual", "-g", "-std=c++11");
end Compiler;
package Linker is
for Switches ("C++") use ("-g"); -- keep debug symbols !
end Linker;
end my_project;