c++boostshared-memorypoint-cloud-librarypcl

pcl::PointCloud in shared memory


I'm looking for a way to share a pcl::PointCloud between two processes without using files on the disk. In particular, I'm interested in using boost shared memory libraries to achieve my scope.

I've just tried the following instruction for the sender:

void * pSharedMemory = ... ; // from wherever
pcl::PointCloud<pcl::PointXYZ>::Ptr ptr = ... ; // from wherever
memcpy ( pSharedMemory , static_cast<void const*>(ptr.get()) , sizeof(pcl::PointCloud<pcl::PointXYZ>) ) ;

and the following for the receiver:

template <typename T> nothing ( T* ) { }

void * pSharedMemory = ... ; // from wherever
pcl::PointCloud<pcl::PointXYZ>::Ptr ptr ( static_cast<pcl::PointCloud<pcl::PointXYZ>*>(pSharedMemory) , &nothing<pcl::PointCloud<pcl::PointXYZ> > ) ; // sets the destructor to do nothing

The sender seems to work because I'm able to visualize the PointCloud from the memory, but on the client side the object is correctly created and populated, but I get a segmentation fault when I try to access the points attribute that should contain the points of the clouds. All the other properties (like width, height, ...) are filled with the correct value.

How can I fix this problem and access the points structure? Or is there another way to achieve my scope??


Solution

  • The problem is when pointers are used internally e.g. in the vector implementations:

    using   VectorType = std::vector< PointT, Eigen::aligned_allocator< PointT > >;
     
    using   CloudVectorType = std::vector< PointCloud< PointT >, Eigen::aligned_allocator< PointCloud< PointT > > >;
    

    These pointers will only be valid in the "original" address space, and don't point inside the shared address space in the first place. Even if they did, the memory might be mapped on a different address in each process, so it would still be undefined behaviour to use them.

    Since PCL doesn't let you override the allocator, this is a dead end, because even if you could make it use interprocess-allocators (using rich pointers like boost::interprocess::offset_ptr<> internally), these would not readily satisfy the extra alignment requirements that the Eigen allocators impose.

    It is very possible to share complicated datastructures in shared memory, but the library must have been built with that in mind at least allowing you to choose/parameterize the container/allocator choices. PCL is not such a library at this time.

    At this point you could consider serializing data between processes. This might be too costly for your use case, so in that case you might need to look at another library.