diff --git a/include/boost/interprocess/detail/shared_dir_helpers.hpp b/include/boost/interprocess/detail/shared_dir_helpers.hpp index 8d9d36f2..fb4e0061 100644 --- a/include/boost/interprocess/detail/shared_dir_helpers.hpp +++ b/include/boost/interprocess/detail/shared_dir_helpers.hpp @@ -28,6 +28,7 @@ #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) && defined(BOOST_INTERPROCESS_WINDOWS) #include + #include #endif namespace boost { @@ -59,32 +60,57 @@ struct shared_dir_constants #if defined(BOOST_INTERPROCESS_HAS_KERNEL_BOOTTIME) #if defined(BOOST_INTERPROCESS_WINDOWS) - //This type will initialize the stamp - template - struct windows_bootstamp + // This type will initialize the stamp. + // The namespace allows future changes to the memory layout without + // causing a crash in older or newer versions of the code being used + // in the same process. + // If the memory layout is changed then the class name version suffix must + // be incremented. + // Note that we use winapi::HeapAlloc/HeapFree for memory allocation + // to avoid any differences in heap allocation across modules + namespace windows_bootstamp { - windows_bootstamp() + template + struct version1 { - //Throw if bootstamp not available - if(!winapi::get_last_bootup_time(stamp)){ - error_info err = system_error_code(); - throw interprocess_exception(err); + version1() + { + std::basic_string stamp; + //Throw if bootstamp not available + if(!winapi::get_last_bootup_time(stamp)){ + error_info err = system_error_code(); + throw interprocess_exception(err); + } + unsigned bytes = (stamp.length() + 1) * sizeof(CharT); + data = static_cast(boost::detail::allocate_raw_heap_memory(bytes)); + length = static_cast(stamp.length()); + stamp.copy(data, length); + data[length] = 0; } - } - //Use std::string. Even if this will be constructed in shared memory, all - //modules/dlls are from this process so internal raw pointers to heap are always valid - std::basic_string stamp; - }; + ~version1() + { + if (data) + boost::detail::free_raw_heap_memory(data); + data = nullptr; + length = 0; + } + + uint32_t length{}; + CharT * data {}; + }; + } template inline void get_bootstamp(std::basic_string &s, bool add = false) { - const windows_bootstamp &bootstamp = windows_intermodule_singleton >::get(); + using bootstamp_type = windows_bootstamp::version1; + const bootstamp_type &bootstamp = windows_intermodule_singleton::get(); + std::basic_string_view stamp(bootstamp.data, bootstamp.length); if(add){ - s += bootstamp.stamp; + s += stamp; } else{ - s = bootstamp.stamp; + s = stamp; } } #elif defined(BOOST_INTERPROCESS_HAS_BSD_KERNEL_BOOTTIME)