Open troopy28 opened 4 months ago
I confirm the existence of this problem on Windows x86 and that the workaround works.
I made the workaround generic:
template <class T, std::size_t N, class Allocator = void, class Options = void>
struct alignas(16) aligned_small_vector : boost::container::small_vector<T, N, Allocator, Options>
{
using boost::container::small_vector<T, N, Allocator, Options>::small_vector;
};
It seems that the implementation for aligned_storage from Boost.Move uses double as the aligner type. Unfortunately, there is a compiler bug, If a user declares a variable with 8 byte alignment, such as a double in x86 the compiler will not realign the stack.
Changing the implementation in Boost.Move to use "__declspec(align)" for 8 byte aligned types shows that MSVC will realign the stack properly:
https://github.com/boostorg/move/commit/d0631eec745828207cf251232cef0d681cb758d8
Could you test that after aplying Boost.Move's commit the issues is fixed?
Description
I recently had a problem using
small_vector
in combination withboost::geometry
. I am using theboost::geometry::expand
function, by giving it two boxes as arguments (full code at the end). This call is resolved toenvelope_range_of_boxes::apply
in the file\boost\geometry\algorithms\detail\envelope\range_of_boxes.hpp
. This function contains the following snippet (line ~260) :interval_range_type
is used as the collection type for a series of geometric calculations. It was revealed upon profiling that these calculations are slow because of a high number of allocations performed by the vector.Since the number of elements is small (I did not find a case with more than 2 elements), a simple way to avoid allocations is to use a
small_vector
instead of thestd::vector
, which I am not expecting to ever need to go to dynamic storage (I am usingsmall_vector
and notstatic_vector
because I am not 100% certain of this) :But then, when calling
boost::geometry::expand
, an assert is triggered when constructing thesmall_vector
, in thesmall_vector_allocator<T, VoidAlloc, Options>::internal_storage()
method -small_vector.hpp
line 545 :It seems like the local variable
intervals
(thesmall_vector
) is not being aligned properly on the stack. This only happens in 32 bits. In 64 bits, it works fine. Please note that I have only been able to test this on MSVC, I do not know if it happens on Linux.How to reproduce
1. boost::geometry modification
Modify the file
\boost\geometry\algorithms\detail\envelope\range_of_boxes.hpp
to change the container fromstd::vector<interval_type>
toboost::container::small_vector<interval_type, 4>
at line 248 :2. Test program
Test program : the
expand
function simply needs to be called on two geographic boxes (rectangles).Workaround
Creating a structure that inherits from the
small_vector
we want to create, and specifying its alignment using an attribute, seems to result in a properly aligned variable :