Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
7e41662
Add intrastructure for new.cc tests
paulhdk Mar 29, 2026
b2e88d9
Test deletion of null pointers
paulhdk Mar 29, 2026
fb8d89f
Test simple allocation and deletion
paulhdk Mar 29, 2026
37175ae
Test simple allocation and deletion with `std::nothrow`
paulhdk Mar 29, 2026
140a2b1
Test sized deletion
paulhdk Mar 29, 2026
c362891
Test aligned allocation and deletion
paulhdk Mar 29, 2026
e1e6801
Test aligned allocation with `std::nothrow`
paulhdk Mar 29, 2026
cf610e2
Test aligned sized delete with `std::nothrow`
paulhdk Mar 29, 2026
7044b9a
Fix formatting
paulhdk Mar 29, 2026
d49ce05
Don't explicilty name std::bad_alloc exception when catching it
paulhdk Mar 30, 2026
297d136
include `<array>` explicitly
paulhdk Mar 30, 2026
df065fc
Replace `std::bit_cast` with `reinterpret_cast`
paulhdk Mar 30, 2026
62c3635
Include `<cstddef>` for use of `std::size_t`
paulhdk Mar 30, 2026
a7ae569
Disable tests when `SNMALLOC_USE_SELF_VENDORED_STL=ON` is set
paulhdk Apr 7, 2026
69dd428
Update src/test/func/new/new.cc
mjp41 Apr 17, 2026
886fd37
Update src/test/func/new/new.cc
mjp41 Apr 17, 2026
5fd0941
clang-format
paulhdk Apr 17, 2026
439a42a
Add print statement for debugging CI failure
paulhdk Apr 27, 2026
8a86e1c
Enable SNMALLOC_TRACING in CI
paulhdk Apr 27, 2026
8d1bfb7
Add debug print "begin throw case"
paulhdk Apr 27, 2026
3ef3814
Apply suggestions from code review
mjp41 Apr 28, 2026
3e2b52c
Apply suggestions from code review
mjp41 Apr 28, 2026
11010fe
Use lambdas instead of function pointers for operator new/delete tests
mjp41 Apr 29, 2026
b7cbae4
Testing NetBSD
mjp41 Apr 29, 2026
6af80e6
Compile new/delete override test at -O0
mjp41 Apr 29, 2026
75fd5d0
Upgrade NetBSD CI to 10.1 with GCC 14
mjp41 Apr 29, 2026
1f71a21
Remove -O0 workaround for new/delete override test
mjp41 Apr 29, 2026
98a87d9
CI fixes
mjp41 Apr 29, 2026
cf82587
Fix C11 desctructtors setting.
mjp41 Apr 29, 2026
80adefa
Removing CI debugging.
mjp41 Apr 29, 2026
9dd722d
Revert back to function pointers instead of lambdas
paulhdk Apr 29, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -213,10 +213,10 @@ jobs:
uses: ./.github/workflows/reusable-vm-build.yml
with:
vm-type: netbsd
vm-version: '9.2'
vm-version: '10.1'
build-type: Release
dependencies: "/usr/sbin/pkg_add cmake ninja-build gcc10"
cmake-flags: -DCMAKE_CXX_COMPILER=/usr/pkg/gcc10/bin/g++
dependencies: "/usr/sbin/pkg_add cmake ninja-build gcc14"
cmake-flags: "-DCMAKE_CXX_COMPILER=/usr/pkg/gcc14/bin/g++ -DSNMALLOC_CLEANUP=CXX11_DESTRUCTORS"

# ============================================================================
# QEMU cross-compilation builds
Expand Down
211 changes: 211 additions & 0 deletions src/test/func/new/new.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,211 @@
#if defined(SNMALLOC_USE_SELF_VENDORED_STL) || \
defined(SNMALLOC_THREAD_SANITIZER_ENABLED)
int main()
{
return 0;
}
#else
# include <array>
# include <snmalloc/override/new.cc>
# include <snmalloc/pal/pal.h>
# include <test/helpers.h>
# include <test/setup.h>

using namespace snmalloc;
constexpr std::array<size_t, 11> align_val_sizes = {
8, 16, 32, 64, 128, 256, 512, 1024, 2048, 4096, OS_PAGE_SIZE};

void test_delete_null()
{
operator delete(nullptr, 42);
operator delete(nullptr, std::nothrow);
operator delete(nullptr, 42, std::align_val_t{OS_PAGE_SIZE});
operator delete(nullptr, std::align_val_t{OS_PAGE_SIZE});
operator delete(nullptr, std::align_val_t{OS_PAGE_SIZE}, std::nothrow);
operator delete[](nullptr);
operator delete[](nullptr, 42);
operator delete[](nullptr, std::nothrow);
operator delete[](nullptr, std::align_val_t{OS_PAGE_SIZE});
operator delete[](nullptr, 42, std::align_val_t{OS_PAGE_SIZE});
operator delete[](nullptr, std::align_val_t{OS_PAGE_SIZE}, std::nothrow);
}

template<typename New_Func>
void test_zero_alloc(New_Func new_func)
{
void* non_zero = new_func(0);
EXPECT(non_zero, "allocation with size '0' did not return a valid pointer");
operator delete(non_zero);
}

// SNMALLOC_EXPORT void* operator new(size_t size)
// SNMALLOC_EXPORT void* operator new[](size_t size)
// SNMALLOC_EXPORT void operator delete(void* p) EXCEPTSPEC
// SNMALLOC_EXPORT void* operator delete[](void* p) EXCEPTSPEC
template<void* (*new_fun)(size_t), void (*del_fun)(void*) EXCEPTSPEC>
void test_new_delete_simple(size_t size)
{
void* non_zero = new_fun(size);
bool caught_bad_alloc = false;
EXPECT(non_zero, "expected valid address, but instead got {}", non_zero);
del_fun(non_zero);

test_zero_alloc(new_fun);

try
{
void* impossible_alloc = new_fun(static_cast<size_t>(-1));
del_fun(impossible_alloc);
}
catch (std::bad_alloc&)
{
caught_bad_alloc = true;
}

EXPECT(
caught_bad_alloc,
"Impossible allocation did not throw std::bad_alloc exception");
}

// SNMALLOC_EXPORT void* operator new(size_t size, const std::nothrow_t&)
// noexcept
// SNMALLOC_EXPORT void* operator new[](size_t size, const std::nothrow_t&)
// noexcept
// SNMALLOC_EXPORT void* operator delete(size_t size, const std::nothrow_t&)
// noexcept
// SNMALLOC_EXPORT void* operator delete[](size_t size, const std::nothrow_t&)
// noexcept
template<
void* (*new_fun)(size_t, const std::nothrow_t&),
void (*del_fun)(void*, const std::nothrow_t&) EXCEPTSPEC>
void test_new_delete_nothrow()
{
void* impossible_alloc_unaligned =
new_fun(static_cast<size_t>(-1), std::nothrow);
EXPECT(
impossible_alloc_unaligned == nullptr,
"Impossible allocation should not succeed");
del_fun(impossible_alloc_unaligned, std::nothrow);

test_zero_alloc([](size_t s) { return new_fun(s, std::nothrow); });
}

// SNMALLOC_EXPORT void operator delete(void* p, size_t size) EXCEPTSPEC
// SNMALLOC_EXPORT void operator delete[](void* p, size_t size) EXCEPTSPEC
template<void* (*new_fun)(size_t), void (*del_fun)(void*, size_t) EXCEPTSPEC>
void test_delete_size(size_t size)
{
void* non_zero = new_fun(size);
EXPECT(non_zero, "expected valid address, but instead got {}", non_zero);
del_fun(non_zero, size);
}

// SNMALLOC_EXPORT void* operator new(size_t size, std::align_val_t val)
// SNMALLOC_EXPORT void* operator new[](size_t size, std::align_val_t val)
// SNMALLOC_EXPORT void operator delete(void* p, std::align_val_t) EXCEPTSPEC
// SNMALLOC_EXPORT void operator delete[](void* p, std::align_val_t) EXCEPTSPEC
template<
void* (*new_fun)(size_t, std::align_val_t),
void (*del_fun)(void*, std::align_val_t) EXCEPTSPEC>
void test_new_delete_aligned(size_t size)
{
for (auto& align_val_size : align_val_sizes)
{
std::align_val_t align_val{align_val_size};
void* aligned_mem = new_fun(size, align_val);
EXPECT(
is_aligned(aligned_mem, align_val_size),
"Memory was not aligned on value {}",
align_val_size);
del_fun(aligned_mem, align_val);

test_zero_alloc([&align_val](size_t s) { return new_fun(s, align_val); });
}
}

// SNMALLOC_EXPORT void* operator new(size_t size, std::align_val_t val, const
// std::nothrow_t&) noexcept
// SNMALLOC_EXPORT void* operator new[](size_t size,
// std::align_val_t val, const std::nothrow_t&) noexcept
template<
void* (*new_fun)(size_t, std::align_val_t, const std::nothrow_t&),
void (*del_fun)(void*, std::align_val_t, const std::nothrow_t&) EXCEPTSPEC>
void test_new_delete_aligned_nothrow()
{
std::align_val_t page_size{OS_PAGE_SIZE};
void* impossible_alloc_aligned =
new_fun(static_cast<size_t>(-1), page_size, std::nothrow);
EXPECT(
impossible_alloc_aligned == nullptr,
"Impossible allocation should not succeed");
del_fun(impossible_alloc_aligned, page_size, std::nothrow);

test_zero_alloc(
[&page_size](size_t s) { return new_fun(s, page_size, std::nothrow); });
}

// SNMALLOC_EXPORT void operator delete(void* p, size_t size, std::align_val_t
// val) EXCEPTSPEC
// SNMALLOC_EXPORT void operator delete[](void* p, size_t size,
// std::align_val_t val) EXCEPTSPEC
template<
void* (*new_fun)(size_t, std::align_val_t),
void (*del_fun)(void*, size_t, std::align_val_t) EXCEPTSPEC>
void test_delete_size_aligned(size_t size)
{
for (auto& align_val_size : align_val_sizes)
{
std::align_val_t align_val{align_val_size};
void* aligned_mem = new_fun(size, align_val);
EXPECT(
is_aligned(aligned_mem, align_val_size),
"Memory was not aligned on value {}",
align_val_size);
del_fun(aligned_mem, size, align_val);
}
}

int main(int argc, char** argv)
{
UNUSED(argc);
UNUSED(argv);

setup();

START_TEST("Test delete / delete[] nullptr");
test_delete_null();

START_TEST("Test new / delete simple");
test_new_delete_simple < operator new, operator delete>(42);
START_TEST("Test new[] / delete[] simple");
test_new_delete_simple < operator new[], operator delete[]>(42);

START_TEST("Test new / delete nothrow");
test_new_delete_nothrow < operator new, operator delete>();
START_TEST("Test new[] / delete[] nothrow");
test_new_delete_nothrow < operator new[], operator delete[]>();

START_TEST("Test delete with size parameter");
test_delete_size < operator new, operator delete>(42);
START_TEST("Test delete[] with size parameter");
test_delete_size < operator new[], operator delete[]>(42);

START_TEST("Test new / delete aligned");
test_new_delete_aligned < operator new, operator delete>(42);
START_TEST("Test new[] / delete[] aligned");
test_new_delete_aligned < operator new[], operator delete[]>(42);

START_TEST("Test non-throwing aligned new / delete");
test_new_delete_aligned_nothrow < operator new, operator delete>();
START_TEST("Test non-throwing aligned new[] / delete[]");
test_new_delete_aligned_nothrow < operator new[], operator delete[]>();

START_TEST("Test non-throwing aligned delete with explicit size");
test_delete_size_aligned < operator new, operator delete>(42);
START_TEST("Test non-throwing aligned delete[] with explicit size");
test_delete_size_aligned < operator new[], operator delete[]>(42);

snmalloc::debug_check_empty();
return 0;
}
#endif
9 changes: 9 additions & 0 deletions src/test/helpers.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
#pragma once
#include <cstddef>
#include <cstdint>
#ifdef _MSC_VER
# define __PRETTY_FUNCTION__ __FUNCSIG__
#endif
Expand Down Expand Up @@ -37,3 +39,10 @@ namespace snmalloc
} while (0)

}

// Based on:
// https://en.cppreference.com/w/cpp/memory/is_sufficiently_aligned.html
bool is_aligned(void* ptr, std::size_t align_val_size)
{
return reinterpret_cast<std::uintptr_t>(ptr) % align_val_size == 0;
}
Loading