Thanks to visit codestin.com
Credit goes to github.com

Skip to content

JsonExporter throws during vector conversion #989

Open
@jennyquynh

Description

@jennyquynh

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

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions