Abort instead of calling std::bad_alloc
This commit is contained in:
@@ -3,12 +3,14 @@
|
|||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <cstdio>
|
||||||
#include <cstdlib>
|
#include <cstdlib>
|
||||||
#include <cstring>
|
#include <cstring>
|
||||||
#include <iostream>
|
#include <iostream>
|
||||||
#include <limits>
|
#include <limits>
|
||||||
#include <new>
|
#include <new>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
#include <typeinfo>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@@ -81,16 +83,25 @@ private:
|
|||||||
* @param size Size of the data area for this block
|
* @param size Size of the data area for this block
|
||||||
* @param prev Pointer to the previous block (nullptr for first block)
|
* @param prev Pointer to the previous block (nullptr for first block)
|
||||||
* @return Pointer to the newly created block
|
* @return Pointer to the newly created block
|
||||||
* @throws std::bad_alloc if memory allocation fails
|
* @note Prints error to stderr and calls std::abort() if memory allocation
|
||||||
|
* fails
|
||||||
*/
|
*/
|
||||||
static Block *create(size_t size, Block *prev) {
|
static Block *create(size_t size, Block *prev) {
|
||||||
if (size > std::numeric_limits<uint32_t>::max()) {
|
if (size > std::numeric_limits<uint32_t>::max()) {
|
||||||
throw std::bad_alloc();
|
std::fprintf(
|
||||||
|
stderr,
|
||||||
|
"ArenaAllocator: Block size %zu exceeds maximum uint32_t value\n",
|
||||||
|
size);
|
||||||
|
std::abort();
|
||||||
}
|
}
|
||||||
void *memory = std::aligned_alloc(
|
void *memory = std::aligned_alloc(
|
||||||
alignof(Block), align_up(sizeof(Block) + size, alignof(Block)));
|
alignof(Block), align_up(sizeof(Block) + size, alignof(Block)));
|
||||||
if (!memory) {
|
if (!memory) {
|
||||||
throw std::bad_alloc();
|
std::fprintf(
|
||||||
|
stderr,
|
||||||
|
"ArenaAllocator: Failed to allocate memory block of size %zu\n",
|
||||||
|
size);
|
||||||
|
std::abort();
|
||||||
}
|
}
|
||||||
size_t total_size = size + (prev ? prev->total_size : 0);
|
size_t total_size = size + (prev ? prev->total_size : 0);
|
||||||
size_t total_used = prev ? prev->total_used + prev->offset : 0;
|
size_t total_used = prev ? prev->total_used + prev->offset : 0;
|
||||||
@@ -155,7 +166,8 @@ public:
|
|||||||
* @param size Number of bytes to allocate (0 returns nullptr)
|
* @param size Number of bytes to allocate (0 returns nullptr)
|
||||||
* @param alignment Required alignment (default: alignof(std::max_align_t))
|
* @param alignment Required alignment (default: alignof(std::max_align_t))
|
||||||
* @return Pointer to allocated memory, or nullptr if size is 0
|
* @return Pointer to allocated memory, or nullptr if size is 0
|
||||||
* @throws std::bad_alloc if memory allocation fails
|
* @note Prints error to stderr and calls std::abort() if memory allocation
|
||||||
|
* fails
|
||||||
*
|
*
|
||||||
* ## Performance:
|
* ## Performance:
|
||||||
* - O(1) amortized allocation time
|
* - O(1) amortized allocation time
|
||||||
@@ -210,7 +222,8 @@ public:
|
|||||||
* `alignof(std::max_align_t)`
|
* `alignof(std::max_align_t)`
|
||||||
* @return Pointer to the reallocated memory (may be the same as ptr or
|
* @return Pointer to the reallocated memory (may be the same as ptr or
|
||||||
* different)
|
* different)
|
||||||
* @throws std::bad_alloc if memory allocation fails
|
* @note Prints error to stderr and calls std::abort() if memory allocation
|
||||||
|
* fails
|
||||||
*
|
*
|
||||||
* ## Behavior:
|
* ## Behavior:
|
||||||
* - If new_size == old_size, returns ptr unchanged
|
* - If new_size == old_size, returns ptr unchanged
|
||||||
@@ -236,12 +249,17 @@ public:
|
|||||||
* @param new_size Desired new size in number of T objects
|
* @param new_size Desired new size in number of T objects
|
||||||
* @return Pointer to the reallocated memory (may be the same as ptr or
|
* @return Pointer to the reallocated memory (may be the same as ptr or
|
||||||
* different)
|
* different)
|
||||||
* @throws std::bad_alloc if memory allocation fails or size overflow occurs
|
* @note Prints error to stderr and calls std::abort() if memory allocation
|
||||||
|
* fails or size overflow occurs
|
||||||
*/
|
*/
|
||||||
template <typename T>
|
template <typename T>
|
||||||
T *realloc(T *ptr, uint32_t old_size, uint32_t new_size) {
|
T *realloc(T *ptr, uint32_t old_size, uint32_t new_size) {
|
||||||
if (size_t(new_size) * sizeof(T) > std::numeric_limits<uint32_t>::max()) {
|
if (size_t(new_size) * sizeof(T) > std::numeric_limits<uint32_t>::max()) {
|
||||||
throw std::bad_alloc();
|
std::fprintf(stderr,
|
||||||
|
"ArenaAllocator: Reallocation size overflow for type %s "
|
||||||
|
"(new_size=%u, sizeof(T)=%zu)\n",
|
||||||
|
typeid(T).name(), new_size, sizeof(T));
|
||||||
|
std::abort();
|
||||||
}
|
}
|
||||||
return static_cast<T *>(realloc_raw(ptr, old_size * sizeof(T),
|
return static_cast<T *>(realloc_raw(ptr, old_size * sizeof(T),
|
||||||
new_size * sizeof(T), alignof(T)));
|
new_size * sizeof(T), alignof(T)));
|
||||||
@@ -257,7 +275,8 @@ public:
|
|||||||
* @tparam Args Types of constructor arguments
|
* @tparam Args Types of constructor arguments
|
||||||
* @param args Arguments to forward to T's constructor
|
* @param args Arguments to forward to T's constructor
|
||||||
* @return Pointer to the constructed object
|
* @return Pointer to the constructed object
|
||||||
* @throws std::bad_alloc if memory allocation fails
|
* @note Prints error to stderr and calls std::abort() if memory allocation
|
||||||
|
* fails
|
||||||
*
|
*
|
||||||
* ## Type Requirements:
|
* ## Type Requirements:
|
||||||
* T must be trivially destructible (std::is_trivially_destructible_v<T>).
|
* T must be trivially destructible (std::is_trivially_destructible_v<T>).
|
||||||
@@ -293,7 +312,8 @@ public:
|
|||||||
* @param size Number of T objects to allocate space for
|
* @param size Number of T objects to allocate space for
|
||||||
* @return Pointer to allocated memory suitable for constructing an array of T
|
* @return Pointer to allocated memory suitable for constructing an array of T
|
||||||
* objects
|
* objects
|
||||||
* @throws std::bad_alloc if memory allocation fails
|
* @note Prints error to stderr and calls std::abort() if memory allocation
|
||||||
|
* fails
|
||||||
*
|
*
|
||||||
* ## Type Requirements:
|
* ## Type Requirements:
|
||||||
* T must be trivially destructible (std::is_trivially_destructible_v<T>).
|
* T must be trivially destructible (std::is_trivially_destructible_v<T>).
|
||||||
@@ -315,7 +335,11 @@ public:
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (size_t(size) * sizeof(T) > std::numeric_limits<uint32_t>::max()) {
|
if (size_t(size) * sizeof(T) > std::numeric_limits<uint32_t>::max()) {
|
||||||
throw std::bad_alloc();
|
std::fprintf(stderr,
|
||||||
|
"ArenaAllocator: Allocation size overflow for type %s "
|
||||||
|
"(size=%u, sizeof(T)=%zu)\n",
|
||||||
|
typeid(T).name(), size, sizeof(T));
|
||||||
|
std::abort();
|
||||||
}
|
}
|
||||||
void *ptr = allocate_raw(sizeof(T) * size, alignof(T));
|
void *ptr = allocate_raw(sizeof(T) * size, alignof(T));
|
||||||
return static_cast<T *>(ptr);
|
return static_cast<T *>(ptr);
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
#include "../benchmarks/test_data.hpp"
|
#include "../benchmarks/test_data.hpp"
|
||||||
#include "parser_comparison.hpp"
|
#include "parser_comparison.hpp"
|
||||||
#include <doctest/doctest.h>
|
#include <doctest/doctest.h>
|
||||||
#include <vector>
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Test helper that uses parser comparison to validate both parsers.
|
* @brief Test helper that uses parser comparison to validate both parsers.
|
||||||
|
|||||||
Reference in New Issue
Block a user