[Interprocess] updating elements in vector of maps fails in optimized code
I'm using Boost 1.46 on Linux x86_64 in combination with gcc version 4.5.1. I'm trying to implement a a sparse matrix in a shared memory segment as a vector of maps. When trying to update previously inserted elements of the matrix, at a certain point, the program either crashes or stalls indefinitely. This only occurs if the gcc optimization is set higher than O0. If compiler optimizations are completely turned off (so using the -O0 switch) the program works as expected. Below, I provide some trimmed code that demonstrates the problem. I would be very grateful if somebody could indicate me what's causing this erratic behavior. Steven #include <iostream> #include <stdexcept> #include <boost/interprocess/managed_shared_memory.hpp> #include <boost/interprocess/containers/map.hpp> #include <boost/interprocess/containers/vector.hpp> #include <boost/interprocess/allocators/allocator.hpp> #define MATSIZE 5 typedef boost::interprocess::managed_shared_memory::segment_manager SegmentManager_t; typedef boost::interprocess::allocator<void , SegmentManager_t> VoidAllocator_t; typedef std::pair<int,double> MapValue_t; typedef boost::interprocess::allocator<MapValue_t , SegmentManager_t> MapValueAllocator_t; typedef boost::interprocess::map<int,double,std::less<int>,MapValueAllocator_t> Map_t; typedef boost::interprocess::allocator<Map_t,SegmentManager_t> MapAllocator_t; typedef boost::interprocess::vector<Map_t,MapAllocator_t> VectorofMaps_t; int main(int argc, char **argv) { VectorofMaps_t::size_type i; int j; Map_t::iterator mapiter; try { boost::interprocess::shared_memory_object::remove("MySharedMemory"); boost::interprocess::managed_shared_memory mfile(boost::interprocess::create_only,"MySharedMemory",65536); VoidAllocator_t alloc_inst (mfile.get_segment_manager()); VectorofMaps_t* pS=mfile.construct<VectorofMaps_t>(boost::interprocess::anonymous_instance)(MATSIZE,Map_t(std::less<int>(),alloc_inst),alloc_inst); for(i=0;i<MATSIZE;++i) { for(j=0;j<MATSIZE;++j) (*pS)[i].insert(std::pair<int,double>(j,1.0)); } for(i=0;i<MATSIZE;++i) { for(j=0;j<MATSIZE;++j) { mapiter=(*pS)[i].find(j); if(mapiter!=(*pS)[i].end()) mapiter->second+=1.0; else (*pS)[i].insert(std::pair<int,double>(j,1.0)); } } for(i=0;i<MATSIZE;++i) { for(mapiter=(*pS)[i].begin();mapiter!=(*pS)[i].end();++mapiter) std::cout<<mapiter->second<<" "; std::cout<<std::endl; } boost::interprocess::shared_memory_object::remove("MySharedMemory"); } catch(boost::interprocess::interprocess_exception e) { std::cerr<<"Interprocess error: "<<e.what(); } catch(std::exception e) { std::cerr<<"Standard exception: "<<e.what(); } catch(...) { std::cerr<<"unknown error"; } }
El 11/05/2011 13:01, Steven Maenhout escribió:
I'm using Boost 1.46 on Linux x86_64 in combination with gcc version 4.5.1. I'm trying to implement a a sparse matrix in a shared memory segment as a vector of maps. When trying to update previously inserted elements of the matrix, at a certain point, the program either crashes or stalls indefinitely. This only occurs if the gcc optimization is set higher than O0. If compiler optimizations are completely turned off (so using the -O0 switch) the program works as expected.
Please try latest trunk code or continue reading. offset_ptr works somewhat outside the standard, since it can point from stack to shared memory and the compiler is allowed to do optimizations that legally break offset_ptr assumptions. The only fix is to disallow some optimizations for offset_ptr set_offset/get_offset code, just like in MSVC. I've inserted some __attribute__((noinline)) in those functions for Boost 1.47. It would be glad if you could me know finding the correct way to make offset_ptr work again in GCC. Maybe we need to insert some asm("") statement to disallow some interprocedual optimizations. Some other relative point implementations, like those used in ACE are not header-only and I think they avoid this kind of problems, although in theory whole-program optimizations can also hurt. Best, Ion
Please try latest trunk code
I just tried the latest trunk code and I'm sorry to report that the GCC specific attribute does not solve all problems. The crashes or indefinite waits have been resolved though. I also noticed that the described symptoms are not merely a result of compiler optimizations. I was experimenting with different GCC optimization parameters in an attempt to identify the guilty ones when I noticed that even when optimizations are completely turned off, some weird behavior "can" occur. When I run the snippet provided below, compiled with -O0, several times, the program behaves as expected about half of the times and in the other runs, the map find function will fail to find any entries, resulting in a matrix consisting of ones instead of twos. In higher optimization levels, the find function fails consistently. Does the snippet always work for MSVC? kind regards, Steven #include <iostream> #include <stdexcept> #include <boost/interprocess/managed_shared_memory.hpp> #include <boost/interprocess/containers/map.hpp> #include <boost/interprocess/containers/vector.hpp> #include <boost/interprocess/allocators/allocator.hpp> #define MATSIZE 5 typedef boost::interprocess::managed_shared_memory::segment_manager SegmentManager_t; typedef boost::interprocess::allocator<void , SegmentManager_t> VoidAllocator_t; typedef std::pair<int,double> MapValue_t; typedef boost::interprocess::allocator<MapValue_t , SegmentManager_t> MapValueAllocator_t; typedef boost::interprocess::map<int,double,std::less<int>,MapValueAllocator_t> Map_t; typedef boost::interprocess::allocator<Map_t,SegmentManager_t> MapAllocator_t; typedef boost::interprocess::vector<Map_t,MapAllocator_t> VectorofMaps_t; int main(int argc, char **argv) { VectorofMaps_t::size_type i; int j; Map_t::iterator mapiter; try { boost::interprocess::shared_memory_object::remove("MySharedMemory"); boost::interprocess::managed_shared_memory mfile(boost::interprocess::create_only,"MySharedMemory",65536); VoidAllocator_t alloc_inst (mfile.get_segment_manager()); VectorofMaps_t* pS=mfile.construct<VectorofMaps_t>(boost::interprocess::anonymous_instance)(MATSIZE,Map_t(std::less<int>(),alloc_inst),alloc_inst); for(i=0;i<MATSIZE;++i) { for(j=0;j<MATSIZE;++j) (*pS)[i].insert(MapValue_t(j,1.0)); } for(i=0;i<MATSIZE;++i) { for(j=0;j<MATSIZE;++j) { std::cout<<"looking for ("<<i<<","<<j<<") "; mapiter=(*pS)[i].find(j); if(mapiter!=(*pS)[i].end()) { std::cout<<"found ("<<i<<","<<mapiter->first<<"), updating from "<<mapiter->second<<" to "; mapiter->second+=1.0; std::cout<<mapiter->second<<std::endl; } else std::cout<<"not found"<<std::endl; } } for(i=0;i<MATSIZE;++i) { for(mapiter=(*pS)[i].begin();mapiter!=(*pS)[i].end();++mapiter) std::cout<<"("<<i<<","<<mapiter->first<<")="<<mapiter->second<<" "; std::cout<<std::endl; } boost::interprocess::shared_memory_object::remove("MySharedMemory"); } catch(boost::interprocess::interprocess_exception e) { std::cerr<<"Interprocess error: "<<e.what(); } catch(std::exception e) { std::cerr<<"Standard exception: "<<e.what(); } catch(...) { std::cerr<<"unknown error"; } }
I also noticed that the described symptoms are not merely a result of compiler optimizations. I was experimenting with different GCC optimization parameters in an attempt to identify the guilty ones when I noticed that even when optimizations are completely turned off, some weird behavior "can" occur. When I run the snippet provided below, compiled with -O0, several times, the program behaves as expected about half of the times and in the other runs, the map find function will fail to find any entries, resulting in a matrix consisting of ones instead of twos. In higher optimization levels, the find function fails consistently.
Any chance valgrind can help? Sounds like unitialized read for me. -- Slava
Any chance valgrind can help? Sounds like unitialized read for me.
Indeed Valgrind shows an uninitialized value issue but the heavy use of templates makes the output quite daunting. I've attached it nonetheless in case somebody wants to help at pinpointing the problem. ==16105== Conditional jump or move depends on uninitialised value(s) ==16105== at 0x4672A0: boost::interprocess::offset_ptr<boost::intrusive::compact_rbtree_node<boost::interprocess::offset_ptr<void, long, unsigned long, 0ul> >, long, unsigned long, 0ul> boost::intrusive::detail::tree_algorithms<boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, true> >::lower_bound<int, boost::intrusive::detail::key_nodeptr_comp<boost::container::containers_detail::rbtree<int, std::pair<int const, double>, boost::container::containers_detail::select1st<std::pair<int const, double> >, std::less<int>, boost::interprocess::allocator<std::pair<int, double>, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index> >
::key_node_compare<boost::container::containers_detail::value_compare_impl<int, std::pair<int const, double>, std::less<int>, boost::container::containers_detail::select1st<std::pair<int const, double> > > >, boost::intrusive::rbtree_impl<boost::intrusive::setopt<boost::intrusive::detail::base_hook_traits<boost::container::containers_detail::rbtree_node<std::pair<int, double>, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul> >, boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, true>, (boost::intrusive::link_mode_type)0, boost::intrusive::default_tag, 3>, boost::container::containers_detail::node_compare<boost::container::containers_detail::value_compare_impl<int, std::pair<int const, double>, std::less<int>, boost::container::containers_detail::select1st<std::pair<int const, double> > >, boost::container::containers_detail::rbtree_node<std::pair<int, double>, boost::interprocess::offset_ptr<void, long, unsig ned long, 0ul> > >, unsigned long, true> > > >(boost::interprocess::offset_ptr<boost::intrusive::compact_rbtree_node<boost::interprocess::offset_ptr<void, long, unsigned long, 0ul> > const, long, unsigned long, 0ul>, int const&, boost::intrusive::detail::key_nodeptr_comp<boost::container::containers_detail::rbtree<int, std::pair<int const, double>, boost::container::containers_detail::select1st<std::pair<int const, double> >, std::less<int>, boost::interprocess::allocator<std::pair<int, double>, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index> > >::key_node_compare<boost::container::containers_detail::value_compare_impl<int, std::pair<int const, double>, std::less<int>, boost::container::containers_detail::select1st<std::pair<int const, double> > > >, boost::intrusive::rbtree_impl<boost::intrusive::setopt<boo st::intrusive::detail::base_hook_traits<boost::container::containers_detail::rbtree_node<std::pair<int, double>, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul> >, boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, true>, (boost::intrusive::link_mode_type)0, boost::intrusive::default_tag, 3>, boost::container::containers_detail::node_compare<boost::container::containers_detail::value_compare_impl<int, std::pair<int const, double>, std::less<int>, boost::container::containers_detail::select1st<std::pair<int const, double> > >, boost::container::containers_detail::rbtree_node<std::pair<int, double>, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul> > >, unsigned long, true> > >) (tree_algorithms.hpp:839) ==16105== by 0x465661: boost::interprocess::offset_ptr<boost::intrusive::compact_rbtree_node<boost::interprocess::offset_ptr<void, long, unsigned long, 0ul> >, long, unsigned long, 0ul> boost::intrusive::detail::tree_algorithms<boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, true> >::find<int, boost::intrusive::detail::key_nodeptr_comp<boost::container::containers_detail::rbtree<int, std::pair<int const, double>, boost::container::containers_detail::select1st<std::pair<int const, double> >, std::less<int>, boost::interprocess::allocator<std::pair<int, double>, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index> > ::key_node_compare<boost::container::containers_detail::value_compare_impl<int, std::pair<int const, double>, std::less<int>, boost::container::containers_detail::select1st<std::pair<int const, double> > > >, boost::intrusive::rbtree_impl<boost::intrusive::setopt<boost::intrusive::detail::base_hook_traits<boost::container::containers_detail::rbtree_node<std::pair<int, double>, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul> >, boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, true>, (boost::intrusive::link_mode_type)0, boost::intrusive::default_tag, 3>, boost::container::containers_detail::node_compare<boost::container::containers_detail::value_compare_impl<int, std::pair<int const, double>, std::less<int>, boost::container::containers_detail::select1st<std::pair<int const, double> > >, boost::container::containers_detail::rbtree_node<std::pair<int, double>, boost::interprocess::offset_ptr<void, long, unsig ned long, 0ul> > >, unsigned long, true> > > >(boost::interprocess::offset_ptr<boost::intrusive::compact_rbtree_node<boost::interprocess::offset_ptr<void, long, unsigned long, 0ul> > const, long, unsigned long, 0ul>, int const&, boost::intrusive::detail::key_nodeptr_comp<boost::container::containers_detail::rbtree<int, std::pair<int const, double>, boost::container::containers_detail::select1st<std::pair<int const, double> >, std::less<int>, boost::interprocess::allocator<std::pair<int, double>, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index> > >::key_node_compare<boost::container::containers_detail::value_compare_impl<int, std::pair<int const, double>, std::less<int>, boost::container::containers_detail::select1st<std::pair<int const, double> > > >, boost::intrusive::rbtree_impl<boost::intrusive::setopt<boo st::intrusive::detail::base_hook_traits<boost::container::containers_detail::rbtree_node<std::pair<int, double>, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul> >, boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, true>, (boost::intrusive::link_mode_type)0, boost::intrusive::default_tag, 3>, boost::container::containers_detail::node_compare<boost::container::containers_detail::value_compare_impl<int, std::pair<int const, double>, std::less<int>, boost::container::containers_detail::select1st<std::pair<int const, double> > >, boost::container::containers_detail::rbtree_node<std::pair<int, double>, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul> > >, unsigned long, true> > >) (tree_algorithms.hpp:758) ==16105== by 0x4644CB: boost::interprocess::offset_ptr<boost::intrusive::compact_rbtree_node<boost::interprocess::offset_ptr<void, long, unsigned long, 0ul> >, long, unsigned long, 0ul> boost::intrusive::rbtree_algorithms<boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, true> >::find<int, boost::intrusive::detail::key_nodeptr_comp<boost::container::containers_detail::rbtree<int, std::pair<int const, double>, boost::container::containers_detail::select1st<std::pair<int const, double> >, std::less<int>, boost::interprocess::allocator<std::pair<int, double>, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index> > ::key_node_compare<boost::container::containers_detail::value_compare_impl<int, std::pair<int const, double>, std::less<int>, boost::container::containers_detail::select1st<std::pair<int const, double> > > >, boost::intrusive::rbtree_impl<boost::intrusive::setopt<boost::intrusive::detail::base_hook_traits<boost::container::containers_detail::rbtree_node<std::pair<int, double>, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul> >, boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, true>, (boost::intrusive::link_mode_type)0, boost::intrusive::default_tag, 3>, boost::container::containers_detail::node_compare<boost::container::containers_detail::value_compare_impl<int, std::pair<int const, double>, std::less<int>, boost::container::containers_detail::select1st<std::pair<int const, double> > >, boost::container::containers_detail::rbtree_node<std::pair<int, double>, boost::interprocess::offset_ptr<void, long, unsig ned long, 0ul> > >, unsigned long, true> > > >(boost::interprocess::offset_ptr<boost::intrusive::compact_rbtree_node<boost::interprocess::offset_ptr<void, long, unsigned long, 0ul> > const, long, unsigned long, 0ul>, int const&, boost::intrusive::detail::key_nodeptr_comp<boost::container::containers_detail::rbtree<int, std::pair<int const, double>, boost::container::containers_detail::select1st<std::pair<int const, double> >, std::less<int>, boost::interprocess::allocator<std::pair<int, double>, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index> > >::key_node_compare<boost::container::containers_detail::value_compare_impl<int, std::pair<int const, double>, std::less<int>, boost::container::containers_detail::select1st<std::pair<int const, double> > > >, boost::intrusive::rbtree_impl<boost::intrusive::setopt<boo st::intrusive::detail::base_hook_traits<boost::container::containers_detail::rbtree_node<std::pair<int, double>, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul> >, boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, true>, (boost::intrusive::link_mode_type)0, boost::intrusive::default_tag, 3>, boost::container::containers_detail::node_compare<boost::container::containers_detail::value_compare_impl<int, std::pair<int const, double>, std::less<int>, boost::container::containers_detail::select1st<std::pair<int const, double> > >, boost::container::containers_detail::rbtree_node<std::pair<int, double>, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul> > >, unsigned long, true> > >) (rbtree_algorithms.hpp:502) ==16105== by 0x4629C6: boost::intrusive::tree_iterator<boost::intrusive::rbtree_impl<boost::intrusive::setopt<boost::intrusive::detail::base_hook_traits<boost::container::containers_detail::rbtree_node<std::pair<int, double>, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul> , boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, true>, (boost::intrusive::link_mode_type)0, boost::intrusive::default_tag, 3>, boost::container::containers_detail::node_compare<boost::container::containers_detail::value_compare_impl<int, std::pair<int const, double>, std::less<int>, boost::container::containers_detail::select1st<std::pair<int const, double> > >, boost::container::containers_detail::rbtree_node<std::pair<int, double>, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul> > >, unsigned long, true> >, false> boost::intrusive::rbtree_impl<boost::intrusive::setopt<boost::intrusive::detail::base_hook_traits<boost::container::containers_detail::rbtree_node<std::pair<int, double>, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul> , boost::intrusive::rbtree_node_traits<boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, true>, (boost::intrusive::link_mode_type)0, boost::intrusive::default_tag, 3>, boost::container::containers_detail::node_compare<boost::container::containers_detail::value_compare_impl<int, std::pair<int const, double>, std::less<int>, boost::container::containers_detail::select1st<std::pair<int const, double> > >, boost::container::containers_detail::rbtree_node<std::pair<int, double>, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul> > >, unsigned long, true> >::find<int, boost::container::containers_detail::rbtree<int, std::pair<int const, double>, boost::container::containers_detail::select1st<std::pair<int const, double> >, std::less<int>, boost::interprocess::allocator<std::pair<int, double>, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index> > ::key_node_compare<boost::container::containers_detail::value_compare_impl<int, std::pair<int const, double>, std::less<int>, boost::container::containers_detail::select1st<std::pair<int const, double> > > > >(int const&, boost::container::containers_detail::rbtree<int, std::pair<int const, double>, boost::container::containers_detail::select1st<std::pair<int const, double> >, std::less<int>, boost::interprocess::allocator<std::pair<int, double>, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index> > >::key_node_compare<boost::container::containers_detail::value_compare_impl<int, std::pair<int const, double>, std::less<int>, boost::container::containers_detail::select1st<std::pair<int const, double> > > >) (rbtree.hpp:1153) ==16105== by 0x46130D: boost::container::containers_detail::rbtree<int, std::pair<int const, double>, boost::container::containers_detail::select1st<std::pair<int const, double> >, std::less<int>, boost::interprocess::allocator<std::pair<int, double>, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index> > >::find(int const&) (tree.hpp:844) ==16105== by 0x460937: boost::container::map<int, double, std::less<int>, boost::interprocess::allocator<std::pair<int, double>, boost::interprocess::segment_manager<char, boost::interprocess::rbtree_best_fit<boost::interprocess::mutex_family, boost::interprocess::offset_ptr<void, long, unsigned long, 0ul>, 0ul>, boost::interprocess::iset_index> > >::find(int const&) (map.hpp:612) ==16105== by 0x45E53A: main (main.cpp:42)
El 12/05/2011 12:23, Steven Maenhout escribió:
I just tried the latest trunk code and I'm sorry to report that the GCC specific attribute does not solve all problems. The crashes or indefinite waits have been resolved though.
Code is wrong, because allocator must be defined as: typedef std::pair<const int,double> MapValue_t; instead of typedef std::pair<const int,double> MapValue_t; usual map declaration is: template < class Key, class T, class Compare = less<Key>, class Allocator = allocator<pair<const Key,T> > > class map; The sad part is that I think this bug should have been detected by the implementation, since it's quite common, and it's curious everything compiled fine with such type change. I hope this helps, Ion
El 12/05/2011 22:14, Ion Gaztañaga escribió: Sorry, it should be (copy/paste error when replying too quickly): Code is wrong, because allocator must be defined as: typedef std::pair<CONST int,double> MapValue_t; instead of typedef std::pair<int,double> MapValue_t;
Code is wrong, because allocator must be defined as:
typedef std::pair<const int,double> MapValue_t;
Indeed that resolves the issues I encountered in the trunk code.
The sad part is that I think this bug should have been detected by the implementation, since it's quite common, and it's curious everything compiled fine with such type change.
well I did ignore the following compilation warning: boost-trunk/boost/interprocess/containers/container/detail/tree.hpp:328:31: warning: returning reference to temporary which does not occur when using the correct "const key" allocator. anyways, thank you very much for your help, Steven
participants (3)
-
Ion Gaztañaga
-
Steven Maenhout
-
Viatcheslav.Sysoltsev@h-d-gmbh.de