7#include "../../include/lammp/impl/mparam.h"
8#include "../../include/lammp/impl/prime_table.h"
9#include "../../include/lammp/impl/tmp_alloc.h"
10#include "../../include/lammp/lmmpn.h"
15#undef lmmp_stack_alloc
17#undef lmmp_leak_tracker
18#define HSIZE sizeof(void*)
26#define heap_alloc_func global_heap.alloc
27#define heap_free_func global_heap.free
28#define realloc_func global_heap.realloc
36#define stack_get_top_func() (lmmp_stack_top)
37#define stack_set_top_func(top) (lmmp_stack_top = top)
50#if LAMMP_DEBUG_MEMORY_LEAK == 1
53 snprintf(msg,
sizeof(msg),
"Default stack allocator is not empty. top: %p, begin: %p, end: %p\n",
80#if LAMMP_DEBUG_MEMORY_LEAK == 1
83 snprintf(msg,
sizeof(msg),
"Older heap allocations not freed: %d block(s)",
heap_alloc_count);
99 *(
void**)p = *pmarker;
109 void* next = *(
void**)marker;
115#include "../../include/lammp/impl/safe_memory.h"
119 snprintf(msg,
sizeof(msg),
"Memory allocation failed (size: %zu bytes)", size);
136 const int max_len =
sizeof(msg) - 1;
140 snprintf(msg + offset, max_len - offset,
"Heap allocations not freed: %d block(s)\n",
heap_alloc_count);
144 offset += snprintf(msg + offset, max_len - offset,
145 "Default stack allocator is not empty. top: %p, begin: %p, end: %p\n",
154#if LAMMP_DEBUG_MEMORY_CHECK == 1
155void*
lmmp_alloc(
size_t size,
const char* func,
int line) {
158#if LAMMP_DEBUG_MEMORY_LEAK == 1
171#if LAMMP_DEBUG_MEMORY_LEAK == 1
180#if LAMMP_DEBUG_MEMORY_CHECK == 1
181void*
lmmp_realloc(
void* oldptr,
size_t new_size,
const char* func,
int line) {
194#if LAMMP_DEBUG_MEMORY_CHECK == 1
195void lmmp_free(
void* ptr,
const char* func,
int line) {
198#if LAMMP_DEBUG_MEMORY_LEAK == 1
207#if LAMMP_DEBUG_MEMORY_LEAK == 1
214#if LAMMP_DEBUG_MEMORY_CHECK != 1
216#define SIZE_SIZE LMMP_ROUND_UP_MULTIPLE(sizeof(size_t), LAMMP_MAX_ALIGN)
224 void* new_top = (
mp_byte_t*)old_top + total_size;
225#if LAMMP_DEBUG_STACK_OVERFLOW_CHECK == 1
228 snprintf(msg,
sizeof(msg),
"Stack overflow (trying to allocate: %zu bytes, stack remaining: %zu bytes)",
234 *(
size_t*)old_top = total_size;
242#if LAMMP_DEBUG_STACK_OVERFLOW_CHECK == 1
245 snprintf(msg,
sizeof(msg),
"Invalid stack pointer (trying to free: %p ; stack start: %p , stack end: %p )", ptr,
252 void* new_top = (
mp_byte_t*)old_top - total_size;
253#if LAMMP_DEBUG_STACK_OVERFLOW_CHECK == 1
256 snprintf(msg,
sizeof(msg),
257 "Stack underflow (trying to free: %p , size: %zu bytes ; stack start: %p , stack end: %p ) \n%s", ptr,
259 "Likely cause: Previous stack buffer overflow corrupted the memory header.");
271 size_t magic_addr_offset;
277#define HEADER_SIZE sizeof(StackHeader)
279#define MAGIC_NUMBER 0xDEADBEEF
280#define MAGIC_SIZE sizeof(unsigned int)
290 size_t base_total_size = HEADER_SIZE + base_data_size;
293 if (extra_size < MAGIC_SIZE) {
294 extra_size = MAGIC_SIZE;
296 size_t total_size = base_total_size + extra_size;
299 void* new_top = (
mp_byte_t*)old_top + total_size;
302 snprintf(msg,
sizeof(msg),
"Stack overflow (alloc: %zu bytes, remaining: %zu bytes)", total_size,
307 StackHeader* header = (StackHeader*)old_top;
308 header->total_size = total_size;
309 header->extra_size = extra_size;
310 header->magic_addr_offset = base_total_size;
311 header->last_ptr = global_stack_last_ptr;
314 void* magic_addr = (
mp_byte_t*)old_top + header->magic_addr_offset;
315 memset(magic_addr, 0, extra_size);
316 for (
size_t i = 0; i + MAGIC_SIZE <= extra_size; i += MAGIC_SIZE) {
317 *(
unsigned int*)((
mp_byte_t*)magic_addr + i) = MAGIC_NUMBER;
321 void* alloc_ptr = (
mp_byte_t*)old_top + HEADER_SIZE;
323 global_stack_last_ptr = alloc_ptr;
334 snprintf(msg,
sizeof(msg),
"Invalid stack pointer, trying to free %p (stack start: %p, end: %p)", ptr,
338 if (ptr != global_stack_last_ptr) {
340 snprintf(msg,
sizeof(msg),
"Invalid stack pointer. Expected %p, but try to free %p", global_stack_last_ptr,
345 StackHeader* header = (StackHeader*)((
mp_byte_t*)ptr - HEADER_SIZE);
346 size_t total_size = header->total_size;
347 size_t extra_size = header->extra_size;
348 void* magic_addr = (
mp_byte_t*)header + header->magic_addr_offset;
349 global_stack_last_ptr = header->last_ptr;
350 int magic_corrupted = 0;
351 for (
size_t i = 0; i + MAGIC_SIZE <= extra_size; i += MAGIC_SIZE) {
352 unsigned int magic = *(
unsigned int*)((
mp_byte_t*)magic_addr + i);
353 if (magic != MAGIC_NUMBER) {
358 if (magic_corrupted) {
361 const int buf_size =
sizeof(error_buf);
363#define SAFE_APPEND(...) \
365 if (offset < buf_size) { \
366 int n = snprintf(error_buf + offset, (size_t)(buf_size - offset), __VA_ARGS__); \
372 SAFE_APPEND(
"Stack buffer overflow detected! Magic number corrupted at %p (ptr: %p, size: %zu)\n", magic_addr,
375 SAFE_APPEND(
" allocated at: [%s]:%d\n", header->func, header->line);
376 SAFE_APPEND(
" total size: %zu bytes\n", header->total_size);
377 SAFE_APPEND(
" extra size: %zu bytes (%.0f%% of user size)\n", header->extra_size,
379 SAFE_APPEND(
" magic offset: %zu\n", header->magic_addr_offset);
385 void* new_top = (
mp_byte_t*)old_top - total_size;
388 snprintf(msg,
sizeof(msg),
"Stack underflow (free: %p, size: %zu; stack start: %p, end: %p)", ptr,
void lmmp_abort(lmmp_error_t type, const char *msg, const char *func, int line)
LAMMP 全局退出函数,内部错误或断言失败时调用,若设置了全局退出函数,则会调用该函数,否则会调用默认的退出函数。
#define LAMMP_THREAD_LOCAL
#define LAMMP_MEMORY_MORE_ALLOC_TIMES
@ LAMMP_ERROR_MEMORY_ALLOC_FAILURE
@ LAMMP_ERROR_MEMORY_LEAK
@ LAMMP_ERROR_MEMORY_FREE_FAILURE
@ LAMMP_ERROR_OUT_OF_BOUNDS
#define LMMP_ROUND_UP_MULTIPLE(a, m)
#define lmmp_leak_tracker
void * lmmp_stack_alloc(size_t size)
栈内存分配函数(使用stack_get_top和stack_set_top)
void lmmp_temp_heap_free_(void *marker)
临时堆内存释放函数
void lmmp_set_heap_allocator(const lmmp_heap_allocator_t *heap)
设置 LAMMP 全局堆内存分配函数
#define stack_set_top_func(top)
void * lmmp_alloc(size_t size)
内存分配函数(调用lmmp_heap_alloc_fn)
void * lmmp_temp_heap_alloc_(void **pmarker, size_t size)
临时堆内存分配函数
void lmmp_stack_free(void *ptr)
栈内存释放函数(使用stack_get_top和stack_set_top)
_Thread_local void * lmmp_stack_begin
void lmmp_stack_reset(size_t size)
LAMMP 全局栈重置函数(通常不需要手动调用)
void lmmp_free(void *ptr)
内存释放函数(调用lmmp_heap_free_fn)
void * lmmp_realloc(void *oldptr, size_t new_size)
内存重分配函数(调用lmmp_realloc_fn)
_Thread_local void * lmmp_stack_top
#define stack_get_top_func()
static _Thread_local int heap_alloc_count
_Thread_local void * lmmp_stack_end
void lmmp_global_init(void)
全局初始化函数(线程局部的)
void lmmp_global_deinit(void)
(线程局部的)全局共享的动态分配的堆内存资源释放函数
static _Thread_local lmmp_heap_allocator_t global_heap
static void lmmp_chech_memory(size_t size, const char *func, int line)
void lmmp_stack_init(void)
LAMMP 全局栈初始化函数(通常不需要手动调用)
int lmmp_alloc_count(int cnt)
堆内存分配计数器(线程局部)
#define LAMMP_DEFAULT_STACK_SIZE
void lmmp_prime_int_table_free_(void)
释放全局素数表
static void * lmmp_realloc_debug(void *ptr, size_t new_size, const char *func, int line)
static void * lmmp_alloc_debug(size_t size, const char *func, int line)
static void lmmp_free_debug(void *ptr, const char *func, int line)