Opened 10 years ago
Last modified 7 years ago
#8276 new Bugs
Shared Memory Access by 32-bit and 64-bit Processes
| Reported by: | Owned by: | Ion Gaztañaga | |
|---|---|---|---|
| Milestone: | To Be Determined | Component: | interprocess |
| Version: | Boost 1.52.0 | Severity: | Showstopper |
| Keywords: | 32Bit, 64Bit | Cc: |
Description
Problem: Exception raised in Segment.find_or_construct<>() call.
Problem: Exception raised in Segment.find_or_construct<>() call.
The system operates if all of the the processes are 64-bit, or if all of the processes are 32-bit.
If the shared memory segment has been constructed by a 64-bit process, attempting to find_or_construct it with a 32-bit process fails. Similary, if the shared memory segment has been constructed by a 32-bit process, attempting to find_of_construct it with a 64-bit process fails.
I have determined that the actual objects in shared memory report different sizes when compiled for 32-bit or 64-bit.
This is a multi-cast PubSub program. It constructs the following complex data structure in shared memory:
// Boost includes
#include <boost\interprocess\managed_shared_memory.hpp>
#include <boost\interprocess\containers\map.hpp>
#include <boost\unordered_map.hpp>
#include <boost\interprocess\allocators\allocator.hpp>
#include <boost\interprocess\containers\vector.hpp>
#include <boost\interprocess\containers\string.hpp>
#include <boost\interprocess\sync\interprocess_mutex.hpp>
#include <boost\interprocess\sync\interprocess_semaphore.hpp>
#include <boost\interprocess\sync\scoped_lock.hpp>
#include <boost\interprocess\detail\move.hpp>
#include <boost\thread.hpp>
#include <boost\foreach.hpp>
#include <boost\format.hpp>
#include <functional>
#include <boost/functional/hash.hpp>
typedef managed_shared_memory::segment_manager segment_manager_t; // this is the segment_manager
// Define the allocators.
typedef boost::interprocess::allocator<void, segment_manager_t> void_allocator; // void_allocator is convertible to any other allocator<T>.
typedef boost::interprocess::allocator<int, segment_manager_t> int_allocator; // allocator for allocating ints.
typedef boost::interprocess::vector<int, int_allocator> int_vector; // an int_vector is a vector of ints.
typedef boost::interprocess::allocator<int_vector, segment_manager_t> int_vector_allocator; // an allocator for allocating vectors of ints.
typedef boost::interprocess::vector<int_vector, int_vector_allocator> int_vector_vector; // an int_vector_vector is a vecctor of (vectors of ints)
typedef boost::interprocess::allocator<interprocess_semaphore, segment_manager_t> semaphore_allocator; // an allocator for interprocess_semaphore
typedef boost::interprocess::allocator<WCHAR, segment_manager_t> wchar_allocator; // an allocator for wide chars.
typedef boost::interprocess::basic_string<WCHAR, std::char_traits<WCHAR>, wchar_allocator> wchar_string; // a basic_string (which supports formatting). This is built on a collection of wide chars, allocated by wchar_alloctor.
class EventMessage {
EnumEventType EventType_; // an enum
EnumEventSubType EventSubType; // an enum
ULONG32 ProcessId_;
ULONG32 ThreadId_;
EnumMyType MyType_; // an enum
wchar_string FullPath_;
GUID GuidPublisher_;
}
// Event allocators
typedef boost::interprocess::allocator<EventMessage, segment_manager_t> EventMessage_allocator; // allocator for allocating EventMessage
typedef boost::interprocess::vector<EventMessage, EventMessage_allocator> EventMessage_vector; // vector of EventMessage objects.
class Subscription {
ULONG32 uSignature_;
ULONG32 uSubscribingProcessId_;
ULONG32 uSubscribingThreadId_;
EnumEventType nEventType_ // an enum
offset_ptr<interprocess_semaphore> pSemaphoreSubscription_;
GUID guidSubscriber_;
BOOL fDestructed;
BOOL fWaiting_;
BOOL fCancelled_;
EventMessage_vector events_; // a shared memory vector of EventMessage
}
// Define the types related to Subscription
typedef boost::interprocess::allocator<Subscription, segment_manager_t> subscription_allocator; // allocator for allocating Subscription
typedef boost::interprocess::allocator<GUID, segment_manager_t> guid_allocator; // allocator for allocating GUID
typedef std::pair<const GUID, Subscription> pair_guid_subscription; // a pair of GUID, Subscription
typedef boost::interprocess::allocator<EnumEventType, segment_manager_t> eventtype_allocator; // allocator for allocating EnumEventType
typedef boost::interprocess::allocator<pair_guid_subscription, segment_manager_t> pair_guid_subscription_allocator; // allocator for pair_guid_subscription
typedef boost::unordered_map<GUID, Subscription, boost::hash<GUID>, std::equal_to<GUID>, pair_guid_subscription_allocator> guid_subscription_map; // a map of GUID => Subscription
typedef std::pair<const EnumEventType, guid_subscription_map> pair_eventtype_pair_guid_subscription; // a pair(EnumEventType, pair(GUID, Subscription))
typedef boost::interprocess::allocator<pair_eventtype_pair_guid_subscription, segment_manager_t> pair_eventtype_pair_guid_subscription_allocator; // allocator for pair(EnumEventType, pair(GUID, Subscription))
typedef boost::unordered_map<EnumEventType, guid_subscription_map, boost::hash<int>, std::equal_to<int>, pair_eventtype_pair_guid_subscription_allocator> eventtype_map_guid_subscription_map; // a map(EnumEventType, map<GUID, Subscription)>
typedef boost::interprocess::vector<Subscription, subscription_allocator> subscription_vector; // a vector of Subscriptions
typedef boost::interprocess::allocator<subscription_vector, segment_manager_t> subscription_vector_allocator; // allocator for allocating a vector of Subscription.
typedef boost::interprocess::allocator<guid_subscription_map, segment_manager_t> guid_subscription_map_allocator; // allocator for allocating a map of GUID => Subscription
typedef boost::interprocess::allocator<eventtype_map_guid_subscription_map, segment_manager_t> eventtype_map_guid_subscription_map_allocator; // allocator for allocating map<EnumEventType, map<GUID, Subscription>>
// This is the single item defined in the segment
class Base {
uint64_t reserved1_;
uint64_t reserved2_;
ULONG32 uSignature_;
interprocess_mutex mutexSharedMemory_
eventtype_map_guid_subscription_map subscriptions_; // a shared memory map of [GUID, Subscription] (the active subscriptions)
}
The following sizes are reported:
64-bit
sizeof(IntPtr): 8
sizeof(ULONG32): 4
sizeof(BOOL): 4
sizeof(EnumEventType): 4
sizeof(EnumEventSubType): 4
sizeof(EnumCloudAppIconBadgeType): 4
sizeof(GUID): 16
sizeof(EventMessage): 72
sizeof(Subscription): 88
sizeof(Base): 104
sizeof(size_t): 8
32-bit:
sizeof(IntPtr): 4
sizeof(ULONG32): 4
sizeof(BOOL): 4
sizeof(EnumEventType): 4
sizeof(EnumEventSubType): 4
sizeof(EnumCloudAppIconBadgeType): 4
sizeof(GUID): 16
sizeof(EventMessage): 60
sizeof(Subscription): 64
sizeof(Base): 72
sizeof(size_t): 4
Note that all of the fundamental types are the same size, but the Boost interprocess sizes are different.
I thought that as of Boost 1.48 all of the sizes were normalized to use the same shared memory sizes whether compiled for 32- or 64-bit.
Perhaps I am doing something wrong. Suggestions will be welcome. Thanks.
Note:
See TracTickets
for help on using tickets.

I'm having a similar issue in Boost 1.57 that I believe is related. A boost vector created in shared memory inside a 64-bit process cannot be "found" in a 32-bit process. It works correctly if both processes are 32-bit.
While the shared memory can be opened, the object inside cannot be found.