Skip to content

Commit bd799f1

Browse files
committed
Ensure the container node size is always properly aligned for pointers
Fixes #171.
1 parent f44fc03 commit bd799f1

5 files changed

Lines changed: 28 additions & 4 deletions

File tree

cmake/get_container_node_sizes.cmake

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -181,7 +181,7 @@ namespace detail
181181
template <typename T>
182182
struct ${container}_node_size
183183
: std::integral_constant<std::size_t,
184-
detail::${container}_node_size<alignof(T)>::value + sizeof(T)>
184+
detail::round_up_to_multiple_of_alignment(detail::${container}_node_size<alignof(T)>::value + sizeof(T), alignof(void*))>
185185
{};
186186
")
187187
endforeach()

include/foonathan/memory/detail/align.hpp

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,13 @@ namespace foonathan
2121
return alignment && (alignment & (alignment - 1)) == 0u;
2222
}
2323

24+
constexpr std::size_t round_up_to_multiple_of_alignment(std::size_t size,
25+
std::size_t alignment) noexcept
26+
{
27+
FOONATHAN_MEMORY_ASSERT(is_valid_alignment(alignment));
28+
return (size + alignment - 1) & ~(alignment - 1);
29+
}
30+
2431
// returns the offset needed to align ptr for given alignment
2532
// alignment must be valid
2633
inline std::size_t align_offset(std::uintptr_t address, std::size_t alignment) noexcept
@@ -45,7 +52,7 @@ namespace foonathan
4552
// returns the minimum alignment required for a node of given size
4653
std::size_t alignment_for(std::size_t size) noexcept;
4754
} // namespace detail
48-
} // namespace memory
55+
} // namespace memory
4956
} // namespace foonathan
5057

5158
#endif // FOONATHAN_MEMORY_DETAIL_ALIGN_HPP_INCLUDED

include/foonathan/memory/detail/container_node_sizes.hpp

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
#ifndef FOONATHAN_MEMORY_DETAIL_CONTAINER_NODE_SIZES_HPP_INCLUDED
55
#define FOONATHAN_MEMORY_DETAIL_CONTAINER_NODE_SIZES_HPP_INCLUDED
66

7+
#include "align.hpp"
78
#include "container_node_sizes_impl.hpp"
89

910
#endif //FOONATHAN_MEMORY_DETAIL_CONTAINER_NODE_SIZES_HPP_INCLUDED

test/detail/align.cpp

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,21 @@
88
using namespace foonathan::memory;
99
using namespace detail;
1010

11+
TEST_CASE("detail::round_up_to_multiple_of_alignment")
12+
{
13+
REQUIRE(round_up_to_multiple_of_alignment(0, 1) == 0);
14+
REQUIRE(round_up_to_multiple_of_alignment(1, 1) == 1);
15+
REQUIRE(round_up_to_multiple_of_alignment(2, 1) == 2);
16+
REQUIRE(round_up_to_multiple_of_alignment(3, 1) == 3);
17+
REQUIRE(round_up_to_multiple_of_alignment(4, 1) == 4);
18+
19+
REQUIRE(round_up_to_multiple_of_alignment(0, 2) == 0);
20+
REQUIRE(round_up_to_multiple_of_alignment(1, 2) == 2);
21+
REQUIRE(round_up_to_multiple_of_alignment(2, 2) == 2);
22+
REQUIRE(round_up_to_multiple_of_alignment(3, 2) == 4);
23+
REQUIRE(round_up_to_multiple_of_alignment(4, 2) == 4);
24+
}
25+
1126
TEST_CASE("detail::align_offset")
1227
{
1328
auto ptr = reinterpret_cast<void*>(0);

tool/node_size_debugger.cpp

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -91,8 +91,9 @@ struct code_serializer
9191
out << "} // namespace detail" << newline << newline << "template <typename T>" << newline
9292
<< "struct " << struct_name(result.container_name) << newline
9393
<< ": std::integral_constant<std::size_t," << newline
94-
<< " detail::" << struct_name(result.container_name) << '<' << alignment
95-
<< ">::value + sizeof(T)>" << newline << "{};" << newline << newline;
94+
<< " detail::round_up_to_multiple_of_alignment(detail::"
95+
<< struct_name(result.container_name) << '<' << alignment
96+
<< ">::value + sizeof(T), alignof(void*))>" << newline << "{};" << newline << newline;
9697
}
9798

9899
void suffix() const

0 commit comments

Comments
 (0)