mirror of
https://github.com/mutouyun/cpp-ipc.git
synced 2025-12-07 01:06:45 +08:00
Add -fsanitize=address for memory leak and out-of-bounds detection.
This commit is contained in:
parent
ec602f50af
commit
872b97f1d3
@ -12,7 +12,7 @@ set(CMAKE_CXX_STANDARD 17)
|
|||||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG")
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -DNDEBUG")
|
||||||
if(NOT MSVC)
|
if(NOT MSVC)
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2")
|
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -O2")
|
||||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_DEBUG} -g -rdynamic")
|
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -g -rdynamic -fsanitize=address")
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
if (MSVC)
|
if (MSVC)
|
||||||
@ -22,8 +22,7 @@ if (MSVC)
|
|||||||
CMAKE_CXX_FLAGS_RELEASE
|
CMAKE_CXX_FLAGS_RELEASE
|
||||||
CMAKE_C_FLAGS
|
CMAKE_C_FLAGS
|
||||||
CMAKE_C_FLAGS_DEBUG
|
CMAKE_C_FLAGS_DEBUG
|
||||||
CMAKE_C_FLAGS_RELEASE
|
CMAKE_C_FLAGS_RELEASE)
|
||||||
)
|
|
||||||
if (LIBIPC_USE_STATIC_CRT)
|
if (LIBIPC_USE_STATIC_CRT)
|
||||||
foreach(CompilerFlag ${CompilerFlags})
|
foreach(CompilerFlag ${CompilerFlags})
|
||||||
string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}")
|
string(REPLACE "/MD" "/MT" ${CompilerFlag} "${${CompilerFlag}}")
|
||||||
|
|||||||
@ -204,6 +204,8 @@ public:
|
|||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
|
/// \struct holder_type_base
|
||||||
|
/// \brief Defines the holder type operation interface.
|
||||||
struct holder_type_base {
|
struct holder_type_base {
|
||||||
virtual ~holder_type_base() noexcept = default;
|
virtual ~holder_type_base() noexcept = default;
|
||||||
virtual std::size_t size() const noexcept = 0;
|
virtual std::size_t size() const noexcept = 0;
|
||||||
@ -213,6 +215,8 @@ struct holder_type_base {
|
|||||||
virtual void dest(void *p, std::size_t n) const noexcept = 0;
|
virtual void dest(void *p, std::size_t n) const noexcept = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/// \struct template <typename Value> holder_type
|
||||||
|
/// \brief Defines generalization operations for different data types.
|
||||||
template <typename Value>
|
template <typename Value>
|
||||||
struct holder_type : holder_type_base {
|
struct holder_type : holder_type_base {
|
||||||
std::size_t size() const noexcept override { return sizeof(Value); }
|
std::size_t size() const noexcept override { return sizeof(Value); }
|
||||||
@ -240,6 +244,10 @@ struct holder_info {
|
|||||||
std::size_t count;
|
std::size_t count;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct holder_data : holder_info {
|
||||||
|
alignas(std::max_align_t) char ___data;
|
||||||
|
};
|
||||||
|
|
||||||
template <typename Value>
|
template <typename Value>
|
||||||
std::size_t full_sizeof(std::size_t count) noexcept {
|
std::size_t full_sizeof(std::size_t count) noexcept {
|
||||||
return ::LIBIMP::round_up(sizeof(detail::holder_info), alignof(std::max_align_t))
|
return ::LIBIMP::round_up(sizeof(detail::holder_info), alignof(std::max_align_t))
|
||||||
@ -252,29 +260,31 @@ std::size_t full_sizeof(holder_info const *info) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void *value_ptr(holder_info *info) noexcept {
|
void *value_ptr(holder_info *info) noexcept {
|
||||||
return reinterpret_cast<void *>(
|
if (info == nullptr) return nullptr;
|
||||||
::LIBIMP::round_up(reinterpret_cast<std::size_t>(info + 1), alignof(std::max_align_t)));
|
return &static_cast<holder_data *>(info)->___data;
|
||||||
}
|
}
|
||||||
|
|
||||||
void const *value_ptr(holder_info const *info) noexcept {
|
void const *value_ptr(holder_info const *info) noexcept {
|
||||||
return reinterpret_cast<void const *>(
|
if (info == nullptr) return nullptr;
|
||||||
::LIBIMP::round_up(reinterpret_cast<std::size_t>(info + 1), alignof(std::max_align_t)));
|
return &static_cast<holder_data const *>(info)->___data;
|
||||||
}
|
}
|
||||||
|
|
||||||
class holder_info_ptr {
|
/// \class holder_data_builder
|
||||||
|
/// \brief The data pointer builder.
|
||||||
|
class holder_data_builder {
|
||||||
allocator const &alloc_;
|
allocator const &alloc_;
|
||||||
holder_info **pptr_;
|
holder_data **pptr_;
|
||||||
std::size_t size_;
|
std::size_t size_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
holder_info_ptr(allocator const &alloc, holder_info *(&ptr), std::size_t sz) noexcept
|
holder_data_builder(allocator const &alloc, holder_data *(&ptr), std::size_t sz) noexcept
|
||||||
: alloc_(alloc)
|
: alloc_(alloc)
|
||||||
, pptr_ (&ptr)
|
, pptr_ (&ptr)
|
||||||
, size_ (::LIBIMP::round_up(sizeof(holder_info), alignof(std::max_align_t)) + sz) {
|
, size_ (detail::full_sizeof<::LIBIMP::byte>(sz)) {
|
||||||
*pptr_ = static_cast<holder_info *>(alloc_.allocate(size_));
|
*pptr_ = static_cast<holder_data *>(alloc_.allocate(size_));
|
||||||
}
|
}
|
||||||
|
|
||||||
~holder_info_ptr() noexcept {
|
~holder_data_builder() noexcept {
|
||||||
if (pptr_ == nullptr) return;
|
if (pptr_ == nullptr) return;
|
||||||
alloc_.deallocate(*pptr_, size_);
|
alloc_.deallocate(*pptr_, size_);
|
||||||
*pptr_ = nullptr;
|
*pptr_ = nullptr;
|
||||||
@ -284,11 +294,11 @@ public:
|
|||||||
return (pptr_ != nullptr) && (*pptr_ != nullptr);
|
return (pptr_ != nullptr) && (*pptr_ != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
holder_info *operator->() const noexcept {
|
holder_data *operator->() const noexcept {
|
||||||
return *pptr_;
|
return *pptr_;
|
||||||
}
|
}
|
||||||
|
|
||||||
holder_info_ptr &operator=(holder_info const &rhs) noexcept {
|
holder_data_builder &operator=(holder_data const &rhs) noexcept {
|
||||||
if (!*this) return *this;
|
if (!*this) return *this;
|
||||||
**pptr_ = rhs;
|
**pptr_ = rhs;
|
||||||
return *this;
|
return *this;
|
||||||
@ -308,7 +318,7 @@ public:
|
|||||||
template <>
|
template <>
|
||||||
class holder<void, true> : public holder_base {
|
class holder<void, true> : public holder_base {
|
||||||
|
|
||||||
detail::holder_info info_;
|
detail::holder_data info_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
template <typename Value>
|
template <typename Value>
|
||||||
@ -385,7 +395,7 @@ public:
|
|||||||
template <>
|
template <>
|
||||||
class holder<void, false> : public holder_base {
|
class holder<void, false> : public holder_base {
|
||||||
|
|
||||||
detail::holder_info *info_ptr_;
|
detail::holder_data *info_ptr_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
holder() noexcept
|
holder() noexcept
|
||||||
@ -397,7 +407,7 @@ public:
|
|||||||
std::enable_if_t<alignof(Value) <= alignof(std::max_align_t), bool> = true>
|
std::enable_if_t<alignof(Value) <= alignof(std::max_align_t), bool> = true>
|
||||||
holder(allocator const &alloc, ::LIBIMP::types<Value>, std::size_t n) : holder() {
|
holder(allocator const &alloc, ::LIBIMP::types<Value>, std::size_t n) : holder() {
|
||||||
LIBIMP_LOG_("holder<void, false>");
|
LIBIMP_LOG_("holder<void, false>");
|
||||||
detail::holder_info_ptr info_p{alloc, info_ptr_, sizeof(Value) * n};
|
detail::holder_data_builder info_p{alloc, info_ptr_, sizeof(Value) * n};
|
||||||
if (!info_p) {
|
if (!info_p) {
|
||||||
log.error("The destination information-pointer failed to be constructed."
|
log.error("The destination information-pointer failed to be constructed."
|
||||||
" type size = ", sizeof(Value),
|
" type size = ", sizeof(Value),
|
||||||
@ -452,7 +462,7 @@ public:
|
|||||||
LIBIMP_LOG_();
|
LIBIMP_LOG_();
|
||||||
auto *des = ::LIBIMP::construct<holder>(p);
|
auto *des = ::LIBIMP::construct<holder>(p);
|
||||||
if (!valid()) return;
|
if (!valid()) return;
|
||||||
detail::holder_info_ptr info_p{alloc, des->info_ptr_, this->sizeof_type() * this->count()};
|
detail::holder_data_builder info_p{alloc, des->info_ptr_, this->sizeof_type() * this->count()};
|
||||||
if (!info_p) {
|
if (!info_p) {
|
||||||
log.error("The destination information-pointer failed to be constructed."
|
log.error("The destination information-pointer failed to be constructed."
|
||||||
" type size = ", this->sizeof_type(),
|
" type size = ", this->sizeof_type(),
|
||||||
|
|||||||
@ -53,8 +53,10 @@ result<int> shm_open_fd(std::string const &name, mode::type type) noexcept {
|
|||||||
log.error("name is empty.");
|
log.error("name is empty.");
|
||||||
return std::make_error_code(std::errc::invalid_argument);
|
return std::make_error_code(std::errc::invalid_argument);
|
||||||
}
|
}
|
||||||
|
// For portable use, a shared memory object should be identified by name of the form /somename.
|
||||||
/// \brief Open the object for read-write access.
|
// see: https://man7.org/linux/man-pages/man3/shm_open.3.html
|
||||||
|
std::string op_name = '/' + name;
|
||||||
|
// Open the object for read-write access.
|
||||||
int flag = O_RDWR;
|
int flag = O_RDWR;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case mode::open:
|
case mode::open:
|
||||||
@ -73,13 +75,13 @@ result<int> shm_open_fd(std::string const &name, mode::type type) noexcept {
|
|||||||
return std::make_error_code(std::errc::invalid_argument);
|
return std::make_error_code(std::errc::invalid_argument);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Create/Open POSIX shared memory bject
|
// Create/Open POSIX shared memory bject.
|
||||||
int fd = ::shm_open(name.c_str(), flag, S_IRUSR | S_IWUSR |
|
int fd = ::shm_open(op_name.c_str(), flag, S_IRUSR | S_IWUSR |
|
||||||
S_IRGRP | S_IWGRP |
|
S_IRGRP | S_IWGRP |
|
||||||
S_IROTH | S_IWOTH);
|
S_IROTH | S_IWOTH);
|
||||||
if (fd == posix::failed) {
|
if (fd == posix::failed) {
|
||||||
auto err = sys::error();
|
auto err = sys::error();
|
||||||
log.error("failed: shm_open(name = ", name,
|
log.error("failed: shm_open(name = ", op_name,
|
||||||
", type = ", type,
|
", type = ", type,
|
||||||
"). error = ", err);
|
"). error = ", err);
|
||||||
return err;
|
return err;
|
||||||
|
|||||||
@ -72,7 +72,7 @@ result<HANDLE> mmap_open(std::string const &file, std::size_t size, mode::type t
|
|||||||
return std::make_error_code(std::errc::invalid_argument);
|
return std::make_error_code(std::errc::invalid_argument);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// \brief Opens a named file mapping object.
|
// Opens a named file mapping object.
|
||||||
auto try_open = [&]() -> result<HANDLE> {
|
auto try_open = [&]() -> result<HANDLE> {
|
||||||
HANDLE h = ::OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, t_name.c_str());
|
HANDLE h = ::OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, t_name.c_str());
|
||||||
if (h == NULL) {
|
if (h == NULL) {
|
||||||
@ -83,7 +83,7 @@ result<HANDLE> mmap_open(std::string const &file, std::size_t size, mode::type t
|
|||||||
return h;
|
return h;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// \brief Creates or opens a named or unnamed file mapping object for a specified file.
|
// Creates or opens a named or unnamed file mapping object for a specified file.
|
||||||
auto try_create = [&]() -> result<HANDLE> {
|
auto try_create = [&]() -> result<HANDLE> {
|
||||||
HANDLE h = ::CreateFileMapping(INVALID_HANDLE_VALUE, detail::get_sa(), PAGE_READWRITE | SEC_COMMIT,
|
HANDLE h = ::CreateFileMapping(INVALID_HANDLE_VALUE, detail::get_sa(), PAGE_READWRITE | SEC_COMMIT,
|
||||||
/// \remark dwMaximumSizeHigh always 0 here.
|
/// \remark dwMaximumSizeHigh always 0 here.
|
||||||
|
|||||||
@ -57,7 +57,7 @@ shared_memory::shared_memory(shared_memory &&other) noexcept
|
|||||||
: shm_(std::exchange(other.shm_, nullptr)) {}
|
: shm_(std::exchange(other.shm_, nullptr)) {}
|
||||||
|
|
||||||
shared_memory &shared_memory::operator=(shared_memory &&rhs) & noexcept {
|
shared_memory &shared_memory::operator=(shared_memory &&rhs) & noexcept {
|
||||||
this->shm_ = std::exchange(rhs.shm_, nullptr);
|
shared_memory(std::move(rhs)).swap(*this);
|
||||||
return *this;
|
return *this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -4,6 +4,7 @@
|
|||||||
#include "libimp/detect_plat.h"
|
#include "libimp/detect_plat.h"
|
||||||
#include "libimp/system.h"
|
#include "libimp/system.h"
|
||||||
#include "libimp/log.h"
|
#include "libimp/log.h"
|
||||||
|
#include "libimp/aligned.h"
|
||||||
|
|
||||||
#include "libpmr/memory_resource.h"
|
#include "libpmr/memory_resource.h"
|
||||||
|
|
||||||
@ -52,7 +53,8 @@ void *new_delete_resource::allocate(std::size_t bytes, std::size_t alignment) no
|
|||||||
}
|
}
|
||||||
#if defined(LIBIMP_CPP_17)
|
#if defined(LIBIMP_CPP_17)
|
||||||
/// \see https://en.cppreference.com/w/cpp/memory/c/aligned_alloc
|
/// \see https://en.cppreference.com/w/cpp/memory/c/aligned_alloc
|
||||||
return std::aligned_alloc(alignment, bytes);
|
/// \remark The size parameter must be an integral multiple of alignment.
|
||||||
|
return std::aligned_alloc(alignment, ::LIBIMP::round_up(bytes, alignment));
|
||||||
#else
|
#else
|
||||||
if (alignment <= alignof(std::max_align_t)) {
|
if (alignment <= alignof(std::max_align_t)) {
|
||||||
/// \see https://en.cppreference.com/w/cpp/memory/c/malloc
|
/// \see https://en.cppreference.com/w/cpp/memory/c/malloc
|
||||||
|
|||||||
@ -8,19 +8,23 @@
|
|||||||
TEST(byte, construct) {
|
TEST(byte, construct) {
|
||||||
{
|
{
|
||||||
imp::byte b;
|
imp::byte b;
|
||||||
|
SUCCEED();
|
||||||
|
}
|
||||||
|
{
|
||||||
|
imp::byte b{};
|
||||||
EXPECT_EQ(int(b), 0);
|
EXPECT_EQ(int(b), 0);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
imp::byte b {123};
|
imp::byte b{123};
|
||||||
EXPECT_EQ(int(b), 123);
|
EXPECT_EQ(int(b), 123);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
imp::byte b {65535};
|
imp::byte b{65535};
|
||||||
EXPECT_EQ(int(b), 255);
|
EXPECT_EQ(int(b), 255);
|
||||||
EXPECT_EQ(std::int8_t(b), -1);
|
EXPECT_EQ(std::int8_t(b), -1);
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
imp::byte b {65536};
|
imp::byte b{65536};
|
||||||
EXPECT_EQ(int(b), 0);
|
EXPECT_EQ(int(b), 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -41,14 +41,18 @@ TEST(small_storage, holder_copy_move_construct) {
|
|||||||
EXPECT_FALSE((std::is_move_assignable<pmr::holder<void, false>>::value));
|
EXPECT_FALSE((std::is_move_assignable<pmr::holder<void, false>>::value));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(small_storage, holder_copy_move) {
|
namespace {
|
||||||
struct foo {
|
|
||||||
|
struct foo {
|
||||||
int i;
|
int i;
|
||||||
foo(int i) : i(i) {}
|
foo(int i) : i(i) {}
|
||||||
foo(foo const &rhs) : i(rhs.i) {}
|
foo(foo const &rhs) : i(rhs.i) {}
|
||||||
foo(foo &&rhs) : i(std::exchange(rhs.i, 0)) {}
|
foo(foo &&rhs) : i(std::exchange(rhs.i, 0)) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
} // namespace
|
||||||
|
|
||||||
|
TEST(small_storage, holder_copy_move_object_stack) {
|
||||||
pmr::allocator alc;
|
pmr::allocator alc;
|
||||||
pmr::holder<foo, true> h1(alc, 1);
|
pmr::holder<foo, true> h1(alc, 1);
|
||||||
pmr::holder<foo, true> h2, h3;
|
pmr::holder<foo, true> h2, h3;
|
||||||
@ -61,7 +65,10 @@ TEST(small_storage, holder_copy_move) {
|
|||||||
h1.destroy(alc);
|
h1.destroy(alc);
|
||||||
h2.destroy(alc);
|
h2.destroy(alc);
|
||||||
h3.destroy(alc);
|
h3.destroy(alc);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(small_storage, holder_copy_move_object_heap) {
|
||||||
|
pmr::allocator alc;
|
||||||
pmr::holder<foo, false> h4(alc, 1);
|
pmr::holder<foo, false> h4(alc, 1);
|
||||||
pmr::holder<foo, false> h5, h6;
|
pmr::holder<foo, false> h5, h6;
|
||||||
h4.copy_to(alc, &h5);
|
h4.copy_to(alc, &h5);
|
||||||
@ -73,17 +80,20 @@ TEST(small_storage, holder_copy_move) {
|
|||||||
h4.destroy(alc);
|
h4.destroy(alc);
|
||||||
h5.destroy(alc);
|
h5.destroy(alc);
|
||||||
h6.destroy(alc);
|
h6.destroy(alc);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(small_storage, holder_copy_move_array_stack) {
|
||||||
|
pmr::allocator alc;
|
||||||
void *ph1 = std::malloc(pmr::holder<void, true>::full_sizeof<int>(10));
|
void *ph1 = std::malloc(pmr::holder<void, true>::full_sizeof<int>(10));
|
||||||
void *ph2 = std::malloc(pmr::holder<void, true>::full_sizeof<int>(10));
|
void *ph2 = std::malloc(pmr::holder<void, true>::full_sizeof<int>(10));
|
||||||
void *ph3 = std::malloc(pmr::holder<void, true>::full_sizeof<int>(10));
|
void *ph3 = std::malloc(pmr::holder<void, true>::full_sizeof<int>(10));
|
||||||
auto *h7 = ::new (ph1) pmr::holder<void, true>(alc, ::LIBIMP::types<int>{}, 10);
|
auto *h7 = ::new (ph1) pmr::holder<void, true>(alc, ::LIBIMP::types<int>{}, 10);
|
||||||
auto *h8 = ::new (ph2) pmr::holder<void, true>;
|
auto *h8 = static_cast<pmr::holder<void, true> *>(ph2);
|
||||||
auto *h9 = ::new (ph2) pmr::holder<void, true>;
|
auto *h9 = static_cast<pmr::holder<void, true> *>(ph3);
|
||||||
h7->copy_to(alc, h8);
|
h7->copy_to(alc, ph2);
|
||||||
EXPECT_EQ(h7->count(), 10);
|
EXPECT_EQ(h7->count(), 10);
|
||||||
EXPECT_EQ(h8->count(), 10);
|
EXPECT_EQ(h8->count(), 10);
|
||||||
h7->move_to(alc, h9);
|
h7->move_to(alc, ph3);
|
||||||
EXPECT_EQ(h7->count(), 0);
|
EXPECT_EQ(h7->count(), 0);
|
||||||
EXPECT_EQ(h9->count(), 10);
|
EXPECT_EQ(h9->count(), 10);
|
||||||
h7->destroy(alc);
|
h7->destroy(alc);
|
||||||
@ -92,7 +102,10 @@ TEST(small_storage, holder_copy_move) {
|
|||||||
std::free(ph1);
|
std::free(ph1);
|
||||||
std::free(ph2);
|
std::free(ph2);
|
||||||
std::free(ph3);
|
std::free(ph3);
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(small_storage, holder_copy_move_array_heap) {
|
||||||
|
pmr::allocator alc;
|
||||||
pmr::holder<void, false> h10(alc, ::LIBIMP::types<int>{}, 10);
|
pmr::holder<void, false> h10(alc, ::LIBIMP::types<int>{}, 10);
|
||||||
pmr::holder<void, false> h11, h12;
|
pmr::holder<void, false> h11, h12;
|
||||||
h10.copy_to(alc, &h11);
|
h10.copy_to(alc, &h11);
|
||||||
@ -110,14 +123,14 @@ TEST(small_storage, sizeof) {
|
|||||||
EXPECT_EQ(sizeof(pmr::holder_null), sizeof(void *));
|
EXPECT_EQ(sizeof(pmr::holder_null), sizeof(void *));
|
||||||
EXPECT_EQ(sizeof(pmr::holder<int, true>), sizeof(void *) + imp::round_up(sizeof(int), alignof(void *)));
|
EXPECT_EQ(sizeof(pmr::holder<int, true>), sizeof(void *) + imp::round_up(sizeof(int), alignof(void *)));
|
||||||
EXPECT_EQ(sizeof(pmr::holder<int, false>), sizeof(void *) + sizeof(void *));
|
EXPECT_EQ(sizeof(pmr::holder<int, false>), sizeof(void *) + sizeof(void *));
|
||||||
EXPECT_EQ(sizeof(pmr::holder<void, true>), sizeof(void *) + sizeof(pmr::detail::holder_info));
|
EXPECT_EQ(sizeof(pmr::holder<void, true>), imp::round_up(sizeof(void *) + sizeof(pmr::detail::holder_data), alignof(std::max_align_t)));
|
||||||
EXPECT_EQ(sizeof(pmr::holder<void, false>), sizeof(void *) + sizeof(void *));
|
EXPECT_EQ(sizeof(pmr::holder<void, false>), sizeof(void *) + sizeof(void *));
|
||||||
|
|
||||||
// pmr::small_storage<4> s1;
|
// pmr::small_storage<4> s1;
|
||||||
EXPECT_TRUE(sizeof(pmr::small_storage<16>) > 16);
|
EXPECT_GT(sizeof(pmr::small_storage<16>) , 16);
|
||||||
EXPECT_TRUE(sizeof(pmr::small_storage<64>) > 64);
|
EXPECT_GT(sizeof(pmr::small_storage<64>) , 64);
|
||||||
EXPECT_TRUE(sizeof(pmr::small_storage<512>) > 512);
|
EXPECT_GT(sizeof(pmr::small_storage<512>) , 512);
|
||||||
EXPECT_TRUE(sizeof(pmr::small_storage<4096>) > 4096);
|
EXPECT_GT(sizeof(pmr::small_storage<4096>), 4096);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(small_storage, construct) {
|
TEST(small_storage, construct) {
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user