Estou tentando usar um unordered_map com uma struct personalizada a key. Sei por outros posts que preciso definir uma função hash personalizada e uma função de comparação. Meu problema é o seguinte: A compilação funciona sem erro para STATIC
uma SHARED
biblioteca. Mas ao executar, test_exec
recebo o seguinte erro quando construo uma STATIC
biblioteca:
AddressSanitizer:DEADLYSIGNAL
=================================================================
==19573==ERROR: AddressSanitizer: FPE on unknown address 0x561e54882917 (pc 0x561e54882917 bp 0x7ffea9e6f580 sp 0x7ffea9e6f580 T0)
#0 0x561e54882917 in std::__detail::_Mod_range_hashing::operator()(unsigned long, unsigned long) const (/home/TEST/minimal_example/build_DEBUG/test_exec+0x4917)
#1 0x561e5488855f in std::__detail::_Hash_code_base<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, std::pair<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const, test::MyEnum>, std::__detail::_Select1st, std::hash<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > >, std::__detail::_Mod_range_hashing, std::__detail::_Default_ranged_hash, true>::_M_bucket_index(unsigned long, unsigned long) const (/home/TEST/minimal_example/build_DEBUG/test_exec+0xa55f)
AddressSanitizer:DEADLYSIGNAL
AddressSanitizer: nested bug in the same thread, aborting
Como faço para que isso funcione para uma STATIC
biblioteca?
teste_lib.h
#ifndef TEST_LIB_H
#define TEST_LIB_H
#include <string>
#include <unordered_map>
namespace test {
enum class MyEnum { A, B, C, D };
using enum MyEnum;
const std::unordered_map<std::string, MyEnum> string_to_enum = {
{"A", A},
{"B", B},
{"C", C},
{"D", D},
};
const std::unordered_map<MyEnum, std::string> enum_to_string = {
{A, "A"},
{B, "B"},
{C, "C"},
{D, "D"},
};
struct MyStruct {
MyEnum my_enum;
unsigned int num;
bool operator==(const MyStruct &other) const {
return (my_enum == other.my_enum) && (num == other.num);
}
};
struct MyStructHash {
std::size_t operator()(const MyStruct &s) const {
return std::hash<MyEnum>{}(s.my_enum) ^
(std::hash<unsigned int>{}(s.num) << 1);
}
};
using MyMap = std::unordered_map<MyStruct, double, MyStructHash>;
MyMap get_map();
const MyMap MAP = get_map();
} // namespace test
#endif
teste_lib.cpp
#include "test_lib.h"
namespace test {
MyMap get_map() {
MyMap map;
map[MyStruct(string_to_enum.at("A"), 2)] = 4.5;
return map;
}
} // namespace test
teste_exec.cpp
#include "test_lib.h"
#include <iostream>
using namespace test;
int main(int ac, char **av) {
auto test = string_to_enum.at("A");
std::cout << enum_to_string.at(test) << std::endl;
}
CMakeLists.txt
cmake_minimum_required(VERSION 3.15)
############################
# project name and version #
############################
project( Test VERSION 0.1 LANGUAGES CXX)
##############################
# set c++ flags and standard #
##############################
set(CMAKE_CXX_STANDARD 20)
set(CMAKE_EXPORT_COMPILE_COMMANDS ON)
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS} -O0 -Wall -Wextra -Wpedantic -Wconversion -Wdouble-promotion -Wno-unused-parameter -Wno-unused-function -Wno-sign-conversion -fsanitize=address")
add_library(test_lib STATIC test_lib.cpp)
set_target_properties(test_lib PROPERTIES PUBLIC_HEADER test_lib.h)
add_executable(test_exec test_exec.cpp)
target_link_libraries(test_exec PUBLIC
test_lib
)
Até agora, construí este exemplo mínimo para descartar quaisquer outros problemas no meu código.
EDITAR:
Depois de definir
extern const MyMap MAP;
em test_lib.h e
const MyMap MAP = get_map();
em test_lib.cpp funciona.