Open
Description
Summary
bad_function_call gets thrown when vectors are attempted to be converted to JSON.
Backtrace
#0 0x00007ffff7b3835a in __cxxabiv1::__cxa_throw (obj=0x7fffa8002470, tinfo=0x7ffff7cecfe8 <typeinfo for std::bad_function_call>,
dest=0x7ffff7b641f0 <std::bad_function_call::~bad_function_call()>) at ../../../../src/libstdc++-v3/libsupc++/eh_throw.cc:81
#1 0x00007ffff7b26670 in std::__throw_bad_function_call () at ../../../../../src/libstdc++-v3/src/c++11/functional.cc:34
#2 0x00007fffe7d623c0 in std::function<void (st_perception_msgs::msg::GeoObstacle_<std::allocator<void> > const&, nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann
::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void>&)>::operator()(st_perception_msgs::msg::GeoObstacle_<std::allocator<void> > const&, nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocat
or<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void>&) const (this=0x5555557a96e0, __args#0=..., __args#1=...) at /usr/include/c++/13/bits/std_function.h:590
#3 0x00007fffe7d4f781 in BT::JsonExporter::addConverter<st_perception_msgs::msg::GeoObstacle_<std::allocator<void> > >(std::function<void (st_perception_msgs::msg::GeoObstacle_<std::allocator<void> > const&, nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_tra
its<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void>&)>, bool)::{lambda(BT::Any const&, nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, std::__cxx11::basic_stri
ng<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void>&)#1}::operator()(BT::Any const&, nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, std:
:__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void>&) const (__closure=0x5555557a96e0, entry=..., json=...)
at /opt/ros/jazzy/include/behaviortree_cpp/json_export.h:185
#4 0x00007fffe7d4f987 in BT::JsonExporter::addConverter<st_perception_msgs::msg::GeoObstacle_<std::allocator<void> > >(std::function<void (st_perception_msgs::msg::GeoObstacle_<std::allocator<void> > const&, nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_tra
its<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void>&)>, bool)::{lambda(BT::Any const&, nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, std::__cxx11::basic_stri
ng<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void>&)#2}::operator()(BT::Any const&, nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, std:
:__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void>&) const (__closure=0x5555557a96e0, entry=..., json=...)
at /opt/ros/jazzy/include/behaviortree_cpp/json_export.h:199
#5 0x00007fffe7db5d93 in std::__invoke_impl<void, BT::JsonExporter::addConverter<st_perception_msgs::msg::GeoObstacle_<std::allocator<void> > >(std::function<void (st_perception_msgs::msg::GeoObstacle_<std::allocator<void> > const&, nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, std::__cxx11::basic_s
tring<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void>&)>, bool)::{lambda(BT::Any const&, nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector,
std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void>&)#2}&, BT::Any const&, nlohmann::json_abi_v3_11_3::basic_json<std::map, st
d::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void>&>(std::__invoke_other, BT::JsonExporter::addConverter<st_percept
ion_msgs::msg::GeoObstacle_<std::allocator<void> > >(std::function<void (st_perception_msgs::msg::GeoObstacle_<std::allocator<void> > const&, nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, doubl
e, std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void>&)>, bool)::{lambda(BT::Any const&, nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long
, unsigned long, double, std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void>&)#2}&, BT::Any const&, nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >,
bool, long, unsigned long, double, std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void>&) (__f=...) at /usr/include/c++/13/bits/invoke.h:61
#6 0x00007fffe7da3b4d in std::__invoke_r<void, BT::JsonExporter::addConverter<st_perception_msgs::msg::GeoObstacle_<std::allocator<void> > >(std::function<void (st_perception_msgs::msg::GeoObstacle_<std::allocator<void> > const&, nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, std::__cxx11::basic_stri
ng<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void>&)>, bool)::{lambda(BT::Any const&, nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, st
d::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void>&)#2}&, BT::Any const&, nlohmann::json_abi_v3_11_3::basic_json<std::map, std::
vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void>&>(BT::JsonExporter::addConverter<st_perception_msgs::msg::GeoObstac
le_<std::allocator<void> > >(std::function<void (st_perception_msgs::msg::GeoObstacle_<std::allocator<void> > const&, nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohm
ann::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void>&)>, bool)::{lambda(BT::Any const&, nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double,
std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void>&)#2}&, BT::Any const&, nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned lon
g, double, std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void>&) (__fn=...)
at /usr/include/c++/13/bits/invoke.h:111
#7 0x00007fffe7d8a506 in std::_Function_handler<void (BT::Any const&, nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vec
tor<unsigned char, std::allocator<unsigned char> >, void>&), BT::JsonExporter::addConverter<st_perception_msgs::msg::GeoObstacle_<std::allocator<void> > >(std::function<void (st_perception_msgs::msg::GeoObstacle_<std::allocator<void> > const&, nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, std::__cxx1
1::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void>&)>, bool)::{lambda(BT::Any const&, nlohmann::json_abi_v3_11_3::basic_json<std::map, st
d::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void>&)#2}>::_M_invoke(std::_Any_data const&, BT::Any const&, nlohmann
::json_abi_v3_11_3::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void>&) (
__functor=..., __args#0=..., __args#1=...) at /usr/include/c++/13/bits/std_function.h:290
#8 0x00007fffeca2d5dd in BT::JsonExporter::toJson(BT::Any const&, nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vector-
-Type <RET> for more, q to quit, c to continue without paging--
<unsigned char, std::allocator<unsigned char> >, void>&) const () from target:/opt/ros/jazzy/lib/libbehaviortree_cpp.so
#9 0x00007fffec9e1003 in BT::ExportBlackboardToJSON[abi:cxx11](BT::Blackboard const&) () from target:/opt/ros/jazzy/lib/libbehaviortree_cpp.so
#10 0x00007fffeca56b8d in BT::Groot2Publisher::generateBlackboardsDump(std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const&) () from target:/opt/ros/jazzy/lib/libbehaviortree_cpp.so
#11 0x00007fffeca59c2d in BT::Groot2Publisher::serverLoop() () from target:/opt/ros/jazzy/lib/libbehaviortree_cpp.so
#12 0x00007ffff7b69db4 in std::execute_native_thread_routine (__p=0x555555a16e80) at ../../../../../src/libstdc++-v3/src/c++11/thread.cc:104
#13 0x00007ffff78d7aa4 in start_thread (arg=<optimized out>) at ./nptl/pthread_create.c:447
#14 0x00007ffff7964c3c in clone3 () at ../sysdeps/unix/sysv/linux/x86_64/clone3.S:78
I believe that the issue lies in this function in json_export.h:
template <typename T>
inline void JsonExporter::addConverter(
std::function<void(const T&, nlohmann::json&)> func, bool add_type)
{
auto converter = [func, add_type](const BT::Any& entry, nlohmann::json& json) {
func(entry.cast<T>(), json);
if(add_type)
{
json["__type"] = BT::demangle(typeid(T));
}
};
to_json_converters_.insert({ typeid(T), std::move(converter) });
//---------------------------------------------
// add the vector<T> converter
auto vector_converter = [converter](const BT::Any& entry, nlohmann::json& json) {
auto& vec = *const_cast<BT::Any&>(entry).castPtr<std::vector<T>>();
for(const auto& item : vec)
{
nlohmann::json item_json;
converter(BT::Any(item), item_json);
json.push_back(item_json);
}
};
to_json_converters_.insert({ typeid(std::vector<T>), std::move(vector_converter) });
}
In which converter
is moved into to_json_converters_
yet is still attempted to be invoked after the move, inside the vector_converter
lambda. This part of the backtrace supports that:
(gdb) f 4
#4 0x00007fffe7d4f987 in BT::JsonExporter::addConverter<st_perception_msgs::msg::GeoObstacle_<std::allocator<void> > >(std::function<void (st_perception_msgs::msg::GeoObstacle_<std::allocator<void> > const&, nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_tra
its<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void>&)>, bool)::{lambda(BT::Any const&, nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, std::__cxx11::basic_stri
ng<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void>&)#2}::operator()(BT::Any const&, nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, std:
:__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void>&) const (__closure=0x5555557a96e0, entry=..., json=...)
at /opt/ros/jazzy/include/behaviortree_cpp/json_export.h:199
199 converter(BT::Any(item), item_json);
(gdb) p converter
$3 = {
__func = {
<std::_Maybe_unary_or_binary_function<void, st_perception_msgs::msg::GeoObstacle_<std::allocator<void> > const&, nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohma
nn::json_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void>&>> = {
<std::binary_function<st_perception_msgs::msg::GeoObstacle_<std::allocator<void> > const&, nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long, unsigned long, double, std::allocator, nlohmann::json_abi_v3_11_3
::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void>&, void>> = {<No data fields>}, <No data fields>},
<std::_Function_base> = {
_M_functor = {
_M_unused = {
_M_object = 0x0,
_M_const_object = 0x0,
_M_function_pointer = 0x0,
_M_member_pointer = NULL
},
_M_pod_data = '\000' <repeats 15 times>
},
_M_manager = 0x0
},
members of std::function<void(const st_perception_msgs::msg::GeoObstacle_<std::allocator<void> >&, nlohmann::json_abi_v3_11_3::basic_json<std::map, std::vector, std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> >, bool, long int, long unsigned int, double, std::allocator, nlohmann::js
on_abi_v3_11_3::adl_serializer, std::vector<unsigned char, std::allocator<unsigned char> >, void>&)>:
_M_invoker = 0x0
},
__add_type = true
}
Replication
Call addConvertor
on an JsonExporter, passing it a to_json function with a custom type. Then invoke JsonExporter::toJson
, passing it a vector of that custom type.
Metadata
Metadata
Assignees
Labels
No labels