LAMMP 4.2.0
Lamina High-Precision Arithmetic Library
载入中...
搜索中...
未找到
memory.c
浏览该文件的文档.
1/**
2 * Copyright (C) 2026 HJimmyK(Jericho Knox)
3 *
4 * This file is part of LAMMP.
5 *
6 * LAMMP is free software: you can redistribute it and/or modify it under
7 * the terms of the GNU Lesser General Public License (LGPL) as published
8 * by the Free Software Foundation; either version 3 of the License, or
9 * (at your option) any later version.
10 *
11 * This program is distributed WITHOUT ANY WARRANTY.
12 *
13 * See <https://www.gnu.org/licenses/>.
14 */
15
16#include "../../../include/lammp/impl/mparam.h"
17#include "../../../include/lammp/impl/prime_table.h"
18#include "../../../include/lammp/impl/tmp_alloc.h"
19#include "../../../include/lammp/lmmpn.h"
20
21#undef lmmp_alloc
22#undef lmmp_realloc
23#undef lmmp_free
24#undef lmmp_stack_alloc
25#undef lmmp_stack_free
26#undef lmmp_leak_tracker
27#define HSIZE sizeof(void*)
28
34
35#define heap_alloc_func global_heap.alloc
36#define heap_free_func global_heap.free
37#define realloc_func global_heap.realloc
38
40
43 .stack_end = NULL,
44 .stack_top = NULL,
45 .pool_begin = NULL,
46 .pool_top = NULL,
47 .remain = 0,
48 .capacity = 0,
49};
50
68
69int lmmp_stack_init(size_t size) {
71 return -1;
72 } else {
75 lmmp_abort(LAMMP_ERROR_MEMORY_ALLOC_FAILURE, "Failed to allocate stack memory", __func__, __LINE__);
76 }
79 if (size > LAMMP_MAX_ALIGN) {
80 // 只有当size大于最大对齐单位时,才分配缓冲池
83 heap_free_func(lmmp_tmpmem_ctx.stack_begin); // Free old stack memory
84 lmmp_abort(LAMMP_ERROR_MEMORY_ALLOC_FAILURE, "Failed to allocate pool memory", __func__, __LINE__);
85 }
89 }
90 return 0;
91 }
92}
93
95 if (heap == NULL)
96 return;
98#if LAMMP_DEBUG_MEMORY_LEAK == 1
99 lmmp_leak_tracker(__func__, __LINE__); // Check for memory leaks before setting new allocator
100#endif
101 global_heap = *heap;
103}
104
105#if LAMMP_DEBUG_MEMORY_CHECK == 1
106typedef struct {
107 uint64_t magic; // 魔数,用于验证有效性
108 size_t user_size; // 用户请求的大小
109 size_t total_size; // 总分配大小(含头部、用户内存、额外内存)
110 size_t extra_size; // 额外分配的内存大小
111 const char* func; // 分配发生的函数名
112 int line; // 分配发生的行号
113 uint32_t guard; // 尾哨兵
114} mem_header;
115
116#define MEM_MAGIC 0xDEADBEEFDEADBEEFULL // deadbeef
117#define MEM_GUARD 0xDEADBEEFUL // deadbeef
118#define EXTRA_MEM_PATTERN 0xAA // 额外内存填充模式
119
120#define ALIGNMENT LAMMP_MAX_ALIGN
121
122static inline size_t align_up(size_t size) {
123 return (size + ALIGNMENT - 1) & ~(ALIGNMENT - 1);
124}
125
126/**
127 * @brief 找到指定模式的连续内存区域,并记录起始和结束位置。
128 */
129static inline void find_corruption_range(
130 const char* data,
131 unsigned char pattern,
132 size_t len,
133 int* first,
134 int* last,
135 int* count
136) {
137 *first = -1;
138 *last = -1;
139 *count = 0;
140
141 for (size_t i = 0; i < len; i++) {
142 if ((unsigned char)data[i] != pattern) {
143 (*count)++;
144 if (*first == -1)
145 *first = (int)i;
146 *last = (int)i;
147 }
148 }
149}
150
151/**
152 * @brief 检查额外内存区域是否被修改。
153 */
154static inline int check_extra_memory_overflow(mem_header* hdr, void* user_ptr, const char* check_func, int check_line) {
155 if (!hdr || !user_ptr || hdr->extra_size == 0)
156 return 0;
157
158 size_t aligned_user_size = align_up(hdr->user_size);
159 char* extra_start = (char*)user_ptr + aligned_user_size;
160
161 int first, last, count;
163
164 if (count > 0) {
165 char error_buf[640];
166 int offset = 0;
167 const int buf_size = sizeof(error_buf);
168
169#define SAFE_APPEND(...) \
170 do { \
171 if (offset < buf_size) { \
172 int n = snprintf(error_buf + offset, (size_t)(buf_size - offset), __VA_ARGS__); \
173 if (n > 0) \
174 offset += n; \
175 } \
176 } while (0)
177
178 SAFE_APPEND("Memory overflow (extra memory corruption) detected!%s", "\n");
179 SAFE_APPEND("Memory header:%s", "\n");
180 SAFE_APPEND(" allocated at: [%s]:%d\n", hdr->func, hdr->line);
181 SAFE_APPEND(" checked at: [%s]:%d\n", check_func, check_line);
182 SAFE_APPEND(" user size: %zu bytes\n", hdr->user_size);
183 SAFE_APPEND(" extra size: %zu bytes (%.0f%% of user size)\n", hdr->extra_size,
185 SAFE_APPEND(" user ptr: %p\n", user_ptr);
186 SAFE_APPEND(" extra memory: %p to %p\n", (void*)extra_start, (void*)(extra_start + hdr->extra_size - 1));
187 SAFE_APPEND(" corrupted range: offset %d to %d (total %d bytes)\n", first, last, count);
188 SAFE_APPEND("Likely cause: Buffer overflow beyond the end of the memory.%s", "\n");
189
190 error_buf[buf_size - 1] = '\0';
192 return 1;
193 }
194 return 0;
195}
196
197/**
198 * @brief 检查内存块的完整性(包括头尾和额外内存区域)。
199 */
200static inline int check_memory_block_integrity(mem_header* hdr, void* user_ptr, const char* check_func, int check_line) {
201 if (!hdr || !user_ptr)
202 return 0;
203
204 if (hdr->magic != MEM_MAGIC || hdr->guard != MEM_GUARD) {
205 char error_buf[240];
207 "Memory header corruption detected!\n"
208 " Magic: 0x%016llx (expected 0x%016llx)\n"
209 " Guard: 0x%08lx (expected 0x%08lx)\n"
210 "Possible overflow or underflow or invalid pointer.",
211 hdr->magic, MEM_MAGIC, (unsigned long)hdr->guard, MEM_GUARD);
213 return 1;
214 }
215
217}
218
219/**
220 * @brief 调试版 malloc
221 * @param size 要分配的内存大小
222 * @param func 分配内存的函数名
223 * @param line 分配内存的行号
224 * @return 分配的内存块的指针
225 */
226static inline void* lmmp_alloc_debug(size_t size, const char* func, int line) {
227 if (size == 0) {
228 lmmp_abort(LAMMP_ERROR_MEMORY_ALLOC_FAILURE, "Allocating zero bytes is not allowed.", func, line);
229 return NULL;
230 }
231
232 size_t extra_size = (size * LAMMP_MEMORY_MORE_ALLOC_TIMES) / 10;
234
235 size_t header_size = align_up(sizeof(mem_header));
236 size_t aligned_user_size = align_up(size);
238
239 void* base = heap_alloc_func(total_size);
240 if (!base) {
241 char msg[128];
242 snprintf(msg, sizeof(msg), "Memory allocation failed (size: %zu bytes, extra: %zu bytes)", size, extra_size);
244 return NULL;
245 }
246
247 mem_header* hdr = (mem_header*)base;
248 void* user_ptr = (char*)base + header_size;
249 void* extra_mem = (char*)user_ptr + aligned_user_size;
250
251 hdr->magic = MEM_MAGIC;
252 hdr->user_size = size;
253 hdr->total_size = total_size;
254 hdr->extra_size = extra_size;
255 hdr->func = func;
256 hdr->line = line;
257 hdr->guard = MEM_GUARD;
258
260
261 return user_ptr;
262}
263
264/**
265 * @brief 调试版 free
266 * @param ptr 指向要释放的内存块的指针
267 * @param func 分配内存的函数名
268 * @param line 分配内存的行号
269 */
270static inline void lmmp_free_debug(void* ptr, const char* func, int line) {
271 if (!ptr)
272 return;
273
274 size_t header_size = align_up(sizeof(mem_header));
275 mem_header* hdr = (mem_header*)((char*)ptr - header_size);
276
278
280}
281
282/**
283 * @brief 调试版 realloc
284 * @param ptr 指向要重新分配的内存块的指针
285 * @param new_size 新的内存大小
286 * @param func 分配内存的函数名
287 * @param line 分配内存的行号
288 * @return 新分配的内存块的指针
289 */
290static inline void* lmmp_realloc_debug(void* ptr, size_t new_size, const char* func, int line) {
291 if (!ptr)
293 if (new_size == 0) {
294 lmmp_abort(LAMMP_ERROR_MEMORY_ALLOC_FAILURE, "Reallocating zero bytes is not allowed.", func, line);
295 return NULL;
296 }
297
298 size_t header_size = align_up(sizeof(mem_header));
299 mem_header* old_hdr = (mem_header*)((char*)ptr - header_size);
300
302
304 if (!new_ptr)
305 return NULL;
306
307 size_t copy_size = (old_hdr->user_size < new_size) ? old_hdr->user_size : new_size;
308 memcpy(new_ptr, ptr, copy_size);
309
311 return new_ptr;
312}
313
314#undef SAFE_APPEND
315#undef MEM_MAGIC
316#undef MEM_GUARD
317#undef ALIGNMENT
318#undef EXTRA_MEM_PATTERN
319
320#endif // LAMMP_DEBUG_MEMORY_CHECK == 1
321
323 if (cnt != 0) {
324 int new_cnt = cnt;
327 return cnt;
328 }
329 return heap_alloc_count;
330}
331
332void lmmp_leak_tracker(const char* func, int line) {
333 char msg[360] = {0};
334 int offset = 0;
335 const int max_len = sizeof(msg) - 1;
336 bool t = false;
337 if (heap_alloc_count != 0) {
338 offset +=
339 snprintf(msg + offset, max_len - offset, "Heap allocations not freed: %d block(s);\n", heap_alloc_count);
340 t = true;
341 }
344 "Default stack allocator is not empty. top: %p, begin: %p, end: %p;\n",
346 t = true;
347 }
350 "Default pool allocator is not empty. top: %p, begin: %p; remain: %zu bytes, capacity: %zu "
351 "bytes;\n",
354 t = true;
355 }
356 if (t) {
358 }
359}
360
361#if LAMMP_DEBUG_MEMORY_CHECK == 1
362void* lmmp_alloc(size_t size, const char* func, int line) {
363 void* ret = lmmp_alloc_debug(size, func, line);
364#if LAMMP_DEBUG_MEMORY_LEAK == 1
366#endif
367 return ret;
368}
369#else
370static inline void lmmp_memory_abort(size_t size, const char* func, int line) {
371 char msg[64];
372 snprintf(msg, sizeof(msg), "Memory allocation failed (size: %zu bytes)", size);
374}
375
376void* lmmp_alloc(size_t size) {
377#if LAMMP_DEBUG_PARAM_ASSERT_CHECK == 1
378 if (size == 0) {
379 lmmp_abort(LAMMP_ERROR_MEMORY_ALLOC_FAILURE, "Allocating zero bytes is not allowed.", __func__, __LINE__);
380 return NULL;
381 }
382#endif // LAMMP_DEBUG_PARAM_ASSERT_CHECK == 1
383 void* ret = heap_alloc_func(size);
384 if (ret == NULL)
386#if LAMMP_DEBUG_MEMORY_LEAK == 1
388#endif
389 return ret;
390}
391#endif
392
393#if LAMMP_DEBUG_MEMORY_CHECK == 1
394void* lmmp_realloc(void* oldptr, size_t new_size, const char* func, int line) {
396 return ret;
397}
398#else
399void* lmmp_realloc(void* oldptr, size_t new_size) {
400#if LAMMP_DEBUG_PARAM_ASSERT_CHECK == 1
401 if (new_size == 0) {
402 lmmp_abort(LAMMP_ERROR_MEMORY_ALLOC_FAILURE, "Reallocating zero bytes is not allowed.", __func__, __LINE__);
403 return NULL;
404 }
405#endif // LAMMP_DEBUG_PARAM_ASSERT_CHECK == 1
407 if (ret == NULL) {
409 }
410 return ret;
411}
412#endif // LAMMP_DEBUG_MEMORY_CHECK == 1
413
414#if LAMMP_DEBUG_MEMORY_CHECK == 1
415void lmmp_free(void* ptr, const char* func, int line) {
417#if LAMMP_DEBUG_MEMORY_LEAK == 1
418 if (ptr != NULL)
420#endif
421}
422#else
423void lmmp_free(void* ptr) {
424 heap_free_func(ptr);
425#if LAMMP_DEBUG_MEMORY_LEAK == 1
426 if (ptr != NULL)
428#endif
429}
430#endif
431
435
uint8_t mp_byte_t
Definition lmmp.h:112
void(* lmmp_heap_free_fn)(void *ptr)
Definition lmmp.h:232
#define LAMMP_MAX_ALIGN
Definition lmmp.h:121
lmmp_heap_alloc_fn alloc
Definition lmmp.h:236
void *(* lmmp_realloc_fn)(void *ptr, size_t size)
Definition lmmp.h:233
void lmmp_abort(lmmp_error_t type, const char *msg, const char *func, int line)
LAMMP 全局退出函数,内部错误或断言失败时调用,若设置了全局退出函数,则会调用该函数,否则会调用默认的退出函数。
Definition abort.c:102
#define LAMMP_THREAD_LOCAL
Definition lmmp.h:139
#define LAMMP_MEMORY_MORE_ALLOC_TIMES
Definition lmmp.h:88
void *(* lmmp_heap_alloc_fn)(size_t size)
Definition lmmp.h:231
@ LAMMP_ERROR_MEMORY_ALLOC_FAILURE
Definition lmmp.h:281
@ LAMMP_ERROR_MEMORY_LEAK
Definition lmmp.h:284
@ LAMMP_ERROR_MEMORY_FREE_FAILURE
Definition lmmp.h:282
@ LAMMP_ERROR_OUT_OF_BOUNDS
Definition lmmp.h:283
#define lmmp_leak_tracker
Definition lmmp.h:427
void lmmp_set_heap_allocator(const lmmp_heap_allocator_t *heap)
设置 LAMMP 全局堆内存分配函数
Definition memory.c:94
#define heap_alloc_func
Definition memory.c:35
_Thread_local lmmp_memory_ctx lmmp_tmpmem_ctx
Definition memory.c:41
void * lmmp_alloc(size_t size)
内存分配函数(调用lmmp_heap_alloc_fn)
Definition memory.c:376
int lmmp_stack_deinit(void)
LAMMP 全局栈释放函数(通常不需要手动调用)
Definition memory.c:51
int lmmp_stack_init(size_t size)
LAMMP 全局栈初始化函数(通常不需要手动调用)
Definition memory.c:69
void lmmp_free(void *ptr)
内存释放函数(调用lmmp_heap_free_fn)
Definition memory.c:423
void * lmmp_realloc(void *oldptr, size_t new_size)
内存重分配函数(调用lmmp_realloc_fn)
Definition memory.c:399
#define realloc_func
Definition memory.c:37
static _Thread_local int heap_alloc_count
Definition memory.c:39
#define heap_free_func
Definition memory.c:36
void lmmp_global_init(void)
全局初始化函数(线程局部的)
Definition memory.c:432
static void lmmp_memory_abort(size_t size, const char *func, int line)
Definition memory.c:370
void lmmp_global_deinit(void)
(线程局部的)全局共享的动态分配的堆内存资源释放函数
Definition memory.c:436
_Thread_local lmmp_heap_allocator_t global_heap
Definition memory.c:29
int lmmp_alloc_count(int cnt)
堆内存分配计数器(线程局部)
Definition memory.c:322
#define LAMMP_DEFAULT_STACK_SIZE
Copyright (C) 2026 HJimmyK(Jericho Knox)
Definition mparam.h:20
#define LAMMP_POOL_SIZE
Definition mparam.h:23
#define t
#define n
void lmmp_prime_int_table_free_(void)
释放全局素数表
void * stack_top
Definition tmp_alloc.h:25
size_t capacity
Definition tmp_alloc.h:29
void * pool_begin
Definition tmp_alloc.h:26
void * stack_end
Definition tmp_alloc.h:24
void * stack_begin
Definition tmp_alloc.h:23
void * pool_top
Definition tmp_alloc.h:27
Copyright (C) 2026 HJimmyK(Jericho Knox)
Definition tmp_alloc.h:22