Why can gdb not find element access functions in `absl::flat_hash_map`?

245 views Asked by At

Problem

I'm trying to debug a program that uses absl::flat_hash_map. However, gdb doesn't find operator[] or .find() for some reason. Why doesn't it find these methods? Is there some workaround?

I tested with -O0 -ggdb and

> gdb --version
GNU gdb (GDB) Fedora Linux 12.1-6.fc37

Example

test.cpp

#include "absl/container/flat_hash_map.h"

absl::flat_hash_map<uint64_t, uint64_t> myMap;

int main() {
    myMap[1] = 1;
}

Debugging it:

Temporary breakpoint 1, main () at test.cpp:6
6           myMap[1] = 1;
(gdb) p myMap[1]
No symbol "operator[]" in current context.
(gdb) p myMap.find(1)
Couldn't find method absl::flat_hash_map<unsigned long, unsigned long, absl::hash_internal::Hash<unsigned long>, std::equal_to<unsigned long>, std::allocator<std::pair<unsigned long const, unsigned long> > >::find
(gdb)

Reproduction

CMakeLists.txt

cmake_minimum_required(VERSION 3.10)

project(abseil_test)

# Abseil requires C++14
set(CMAKE_CXX_STANDARD 14)
add_compile_options(-ggdb -O0)

# Process Abseil's CMake build system
add_subdirectory(abseil-cpp)

add_executable(test test.cpp)

target_link_libraries(test absl::base absl::raw_hash_set absl::hash)

Put test.cpp and CMakeLists.txt into a folder and run:

git clone https://github.com/abseil/abseil-cpp.git
mkdir build
cd build
cmake ..
cmake --build . --target test
gdb ./test -ex start -ex 'print myMap[1]'
1

There are 1 answers

0
n. m. could be an AI On

The reason is that gdb is not a C++ compiler. Evaluating a C++ expression can involve a lot more than gdb is capable of. For example, the operator[] of absl hash map is actually a template and calling myMap[1] would need to instantiate it and perform overload resolution.

There are more reasons than that, because in simpler cases one would be able to write something like myMap.'operator[]<uint64_t>'(1) (instantiate manually, so to speak). However, this particular class is probably just too much for poor gdb, so it doesn't work.

The usual (annoying) workaround is compile in the function you want to call as a standalone (non-member) non-template function, so that the syntax is simple enough for gdb to understand.

uint64_t myGet(absl::flat_hash_map<uint64_t, uint64_t>& table,
               uint64_t key)
{
   return table[key];
}