LAMMP 4.1.0
Lamina High-Precision Arithmetic Library
载入中...
搜索中...
未找到
lmmp.h 文件参考
#include <stddef.h>
#include <stdint.h>
#include <stdlib.h>
#include <string.h>
+ lmmp.h 的引用(Include)关系图:
+ 此图展示该文件直接或间接的被哪些文件引用了:

浏览源代码.

结构体

struct  lmmp_heap_allocator_t
 

宏定义

#define LAMMP_API   __declspec(dllimport)
 
#define LAMMP_DEBUG_ASSERT_CHECK   0
 
#define LAMMP_DEBUG_MEMORY_CHECK   0
 
#define LAMMP_DEBUG_MEMORY_LEAK   0
 
#define LAMMP_DEBUG_PARAM_ASSERT_CHECK   0
 
#define LAMMP_DEBUG_STACK_OVERFLOW_CHECK   0
 
#define LAMMP_MAX_ALIGN   16
 
#define LAMMP_MEMORY_MORE_ALLOC_TIMES   1
 
#define LAMMP_THREAD_LOCAL   _Thread_local
 
#define LIMB_BITS   64
 
#define LIMB_BYTES   8
 
#define LIMB_MAX   (~(mp_limb_t)0)
 
#define LLIMB_BITS   32
 
#define LLIMB_BYTES   4
 
#define LLIMB_MASK   ((mp_limb_t)0xffffffff)
 
#define LMMP_ABS(x)   ((x) >= 0 ? (x) : -(x))
 
#define lmmp_assert(x)
 
#define lmmp_copy(dst, src, n)   memmove(dst, src, (n) << 3)
 
#define lmmp_debug_assert(x)   ((void)0)
 
#define lmmp_leak_tracker   ((void)0)
 
#define LMMP_MAX(h, i)   ((h) > (i) ? (h) : (i))
 
#define LMMP_MIN(l, o)   ((l) < (o) ? (l) : (o))
 
#define lmmp_param_assert(x)   ((void)0)
 
#define LMMP_POW2_Q(n)   (((n) & ((n) - 1)) == 0)
 
#define LMMP_ROUND_UP_MULTIPLE(a, m)   ((a) + (m) - 1 - ((a) + (m) - 1) % (m))
 
#define LMMP_SWAP(x, y, type)
 
#define lmmp_zero(dst, n)   memset(dst, 0, (n) << 3)
 
#define LOG2_LIMB_BITS   6
 
#define STATIC_ASSERT(cond, msg)   typedef char static_assert_##__LINE__[(cond) ? 1 : -1]
 

类型定义

typedef void(* lmmp_abort_fn) (lmmp_error_t type, const char *msg, const char *func, int line)
 LAMMP 全局退出函数指针类型
 
typedef void *(* lmmp_heap_alloc_fn) (size_t size)
 
typedef void(* lmmp_heap_free_fn) (void *ptr)
 
typedef void *(* lmmp_realloc_fn) (void *ptr, size_t size)
 
typedef size_t mp_bitcnt_t
 
typedef uint8_t mp_byte_t
 
typedef uint64_t mp_limb_t
 
typedef mp_limb_tmp_ptr
 
typedef uint64_t mp_size_t
 
typedef int64_t mp_slimb_t
 
typedef const mp_limb_tmp_srcptr
 
typedef int64_t mp_ssize_t
 
typedef char static_assert___LINE__[(sizeof(void *)==8) ? 1 :-1]
 

枚举

enum  lmmp_error_t {
  LAMMP_ERROR_ASSERT_FAILURE = 1 , LAMMP_ERROR_DEBUG_ASSERT_FAILURE = 2 , LAMMP_ERROR_PARAM_ASSERT_FAILURE = 3 , LAMMP_ERROR_MEMORY_ALLOC_FAILURE = 4 ,
  LAMMP_ERROR_MEMORY_FREE_FAILURE = 5 , LAMMP_ERROR_OUT_OF_BOUNDS = 6 , LAMMP_ERROR_MEMORY_LEAK = 7 , LAMMP_ERROR_UNEXPECTED_ERROR = 8
}
 

函数

void lmmp_abort (lmmp_error_t type, const char *msg, const char *func, int line)
 LAMMP 全局退出函数,内部错误或断言失败时调用,若设置了全局退出函数,则会调用该函数,否则会调用默认的退出函数。
 
void * lmmp_alloc (size_t size)
 内存分配函数(调用lmmp_heap_alloc_fn)
 
int lmmp_alloc_count (int cnt)
 堆内存分配计数器(线程局部)
 
void lmmp_free (void *ptr)
 内存释放函数(调用lmmp_heap_free_fn)
 
void lmmp_global_deinit (void)
 (线程局部的)全局共享的动态分配的堆内存资源释放函数
 
void lmmp_global_init (void)
 全局初始化函数(线程局部的)
 
void lmmp_leak_tracker (const char *func, int line)
 内存泄漏检测器
 
void * lmmp_realloc (void *ptr, size_t size)
 内存重分配函数(调用lmmp_realloc_fn)
 
lmmp_abort_fn lmmp_set_abort_fn (lmmp_abort_fn func)
 设置 LAMMP 全局退出函数(所有线程均生效)
 
void lmmp_set_heap_allocator (const lmmp_heap_allocator_t *heap)
 设置 LAMMP 全局堆内存分配函数
 
void * lmmp_stack_alloc (size_t size)
 栈内存分配函数(使用stack_get_top和stack_set_top)
 
void lmmp_stack_free (void *ptr)
 栈内存释放函数(使用stack_get_top和stack_set_top)
 
void lmmp_stack_init (void)
 LAMMP 全局栈初始化函数(通常不需要手动调用)
 
void lmmp_stack_reset (size_t size)
 LAMMP 全局栈重置函数(通常不需要手动调用)
 

结构体说明

◆ lmmp_heap_allocator_t

struct lmmp_heap_allocator_t

在文件 lmmp.h91 行定义.

+ lmmp_heap_allocator_t 的协作图:
成员变量
lmmp_heap_alloc_fn alloc
lmmp_heap_free_fn free
lmmp_realloc_fn realloc

宏定义说明

◆ LAMMP_API

#define LAMMP_API   __declspec(dllimport)

在文件 lmmp.h64 行定义.

◆ LAMMP_DEBUG_ASSERT_CHECK

#define LAMMP_DEBUG_ASSERT_CHECK   0

在文件 lmmp.h51 行定义.

◆ LAMMP_DEBUG_MEMORY_CHECK

#define LAMMP_DEBUG_MEMORY_CHECK   0

在文件 lmmp.h53 行定义.

◆ LAMMP_DEBUG_MEMORY_LEAK

#define LAMMP_DEBUG_MEMORY_LEAK   0

在文件 lmmp.h55 行定义.

◆ LAMMP_DEBUG_PARAM_ASSERT_CHECK

#define LAMMP_DEBUG_PARAM_ASSERT_CHECK   0

在文件 lmmp.h52 行定义.

◆ LAMMP_DEBUG_STACK_OVERFLOW_CHECK

#define LAMMP_DEBUG_STACK_OVERFLOW_CHECK   0

在文件 lmmp.h50 行定义.

◆ LAMMP_MAX_ALIGN

#define LAMMP_MAX_ALIGN   16

在文件 lmmp.h219 行定义.

◆ LAMMP_MEMORY_MORE_ALLOC_TIMES

#define LAMMP_MEMORY_MORE_ALLOC_TIMES   1

在文件 lmmp.h54 行定义.

◆ LAMMP_THREAD_LOCAL

#define LAMMP_THREAD_LOCAL   _Thread_local

在文件 lmmp.h237 行定义.

◆ LIMB_BITS

#define LIMB_BITS   64

在文件 lmmp.h221 行定义.

◆ LIMB_BYTES

#define LIMB_BYTES   8

在文件 lmmp.h222 行定义.

◆ LIMB_MAX

#define LIMB_MAX   (~(mp_limb_t)0)

在文件 lmmp.h224 行定义.

◆ LLIMB_BITS

#define LLIMB_BITS   32

在文件 lmmp.h225 行定义.

◆ LLIMB_BYTES

#define LLIMB_BYTES   4

在文件 lmmp.h226 行定义.

◆ LLIMB_MASK

#define LLIMB_MASK   ((mp_limb_t)0xffffffff)

在文件 lmmp.h227 行定义.

◆ LMMP_ABS

#define LMMP_ABS (   x)    ((x) >= 0 ? (x) : -(x))

在文件 lmmp.h346 行定义.

◆ lmmp_assert

#define lmmp_assert (   x)
值:
do { \
if (!(x)) { \
lmmp_abort(LAMMP_ERROR_ASSERT_FAILURE, #x, __func__, __LINE__); \
} \
} while (0)
@ LAMMP_ERROR_ASSERT_FAILURE
Definition lmmp.h:133

在文件 lmmp.h370 行定义.

371 { \
372 if (!(x)) { \
373 lmmp_abort(LAMMP_ERROR_ASSERT_FAILURE, #x, __func__, __LINE__); \
374 } \
375 } while (0)

◆ lmmp_copy

#define lmmp_copy (   dst,
  src,
 
)    memmove(dst, src, (n) << 3)

在文件 lmmp.h364 行定义.

◆ lmmp_debug_assert

#define lmmp_debug_assert (   x)    ((void)0)

在文件 lmmp.h387 行定义.

◆ lmmp_leak_tracker

#define lmmp_leak_tracker   ((void)0)

在文件 lmmp.h316 行定义.

◆ LMMP_MAX

#define LMMP_MAX (   h,
 
)    ((h) > (i) ? (h) : (i))

在文件 lmmp.h350 行定义.

◆ LMMP_MIN

#define LMMP_MIN (   l,
 
)    ((l) < (o) ? (l) : (o))

在文件 lmmp.h348 行定义.

◆ lmmp_param_assert

#define lmmp_param_assert (   x)    ((void)0)

在文件 lmmp.h398 行定义.

◆ LMMP_POW2_Q

#define LMMP_POW2_Q (   n)    (((n) & ((n) - 1)) == 0)

在文件 lmmp.h359 行定义.

◆ LMMP_ROUND_UP_MULTIPLE

#define LMMP_ROUND_UP_MULTIPLE (   a,
 
)    ((a) + (m) - 1 - ((a) + (m) - 1) % (m))

在文件 lmmp.h361 行定义.

◆ LMMP_SWAP

#define LMMP_SWAP (   x,
  y,
  type 
)
值:
do { \
type _swap_ = (x); \
(x) = (y); \
(y) = _swap_; \
} while (0)

在文件 lmmp.h352 行定义.

353 { \
354 type _swap_ = (x); \
355 (x) = (y); \
356 (y) = _swap_; \
357 } while (0)

◆ lmmp_zero

#define lmmp_zero (   dst,
 
)    memset(dst, 0, (n) << 3)

在文件 lmmp.h366 行定义.

◆ LOG2_LIMB_BITS

#define LOG2_LIMB_BITS   6

在文件 lmmp.h223 行定义.

◆ STATIC_ASSERT

#define STATIC_ASSERT (   cond,
  msg 
)    typedef char static_assert_##__LINE__[(cond) ? 1 : -1]

在文件 lmmp.h246 行定义.

类型定义说明

◆ lmmp_abort_fn

typedef void(* lmmp_abort_fn) (lmmp_error_t type, const char *msg, const char *func, int line)

LAMMP 全局退出函数指针类型

参数
type退出类型(可以查看lmmp_abort函数对此参数的说明,这里不再重复)
msg退出信息,取决于type
func退出处的函数名
line退出处的行号

在文件 lmmp.h150 行定义.

◆ lmmp_heap_alloc_fn

typedef void *(* lmmp_heap_alloc_fn) (size_t size)

在文件 lmmp.h87 行定义.

◆ lmmp_heap_free_fn

typedef void(* lmmp_heap_free_fn) (void *ptr)

在文件 lmmp.h88 行定义.

◆ lmmp_realloc_fn

typedef void *(* lmmp_realloc_fn) (void *ptr, size_t size)

在文件 lmmp.h89 行定义.

◆ mp_bitcnt_t

typedef size_t mp_bitcnt_t

在文件 lmmp.h217 行定义.

◆ mp_byte_t

typedef uint8_t mp_byte_t

在文件 lmmp.h210 行定义.

◆ mp_limb_t

typedef uint64_t mp_limb_t

在文件 lmmp.h211 行定义.

◆ mp_ptr

typedef mp_limb_t* mp_ptr

在文件 lmmp.h215 行定义.

◆ mp_size_t

typedef uint64_t mp_size_t

在文件 lmmp.h212 行定义.

◆ mp_slimb_t

typedef int64_t mp_slimb_t

在文件 lmmp.h213 行定义.

◆ mp_srcptr

typedef const mp_limb_t* mp_srcptr

在文件 lmmp.h216 行定义.

◆ mp_ssize_t

typedef int64_t mp_ssize_t

在文件 lmmp.h214 行定义.

◆ static_assert___LINE__

typedef char static_assert___LINE__[(sizeof(void *)==8) ? 1 :-1]

在文件 lmmp.h249 行定义.

枚举类型说明

◆ lmmp_error_t

枚举值
LAMMP_ERROR_ASSERT_FAILURE 
LAMMP_ERROR_DEBUG_ASSERT_FAILURE 
LAMMP_ERROR_PARAM_ASSERT_FAILURE 
LAMMP_ERROR_MEMORY_ALLOC_FAILURE 
LAMMP_ERROR_MEMORY_FREE_FAILURE 
LAMMP_ERROR_OUT_OF_BOUNDS 
LAMMP_ERROR_MEMORY_LEAK 
LAMMP_ERROR_UNEXPECTED_ERROR 

在文件 lmmp.h132 行定义.

132 {
lmmp_error_t
Definition lmmp.h:132
@ LAMMP_ERROR_MEMORY_ALLOC_FAILURE
Definition lmmp.h:136
@ LAMMP_ERROR_DEBUG_ASSERT_FAILURE
Definition lmmp.h:134
@ LAMMP_ERROR_UNEXPECTED_ERROR
Definition lmmp.h:140
@ LAMMP_ERROR_MEMORY_LEAK
Definition lmmp.h:139
@ LAMMP_ERROR_PARAM_ASSERT_FAILURE
Definition lmmp.h:135
@ LAMMP_ERROR_MEMORY_FREE_FAILURE
Definition lmmp.h:137
@ LAMMP_ERROR_OUT_OF_BOUNDS
Definition lmmp.h:138

函数说明

◆ lmmp_abort()

void lmmp_abort ( lmmp_error_t  type,
const char *  msg,
const char *  func,
int  line 
)

LAMMP 全局退出函数,内部错误或断言失败时调用,若设置了全局退出函数,则会调用该函数,否则会调用默认的退出函数。

参数
msg退出信息,assert类型的错误信息通常仅包含断言内容,其他类型的错误则因类型不同而不同。
func退出处的函数名
line退出处的行号
type退出类型。有以下几个类型:
   1. ASSERT_FAILURE (枚举值为1)为lmmp_assert触发的退出,lmmp_assert触发的普通退出几乎不可能发生,
        其通常代表不可能发生的计算错误,可能表明程序执行此处时必须正确的输入错误。比如预期无进位的加法产生了进位。
        此类错误不可接受,会导致计算无法继续进行,导致程序崩溃。

   2. DEBUG_ASSERT_FAILURE (枚举值为2)为lmmp_debug_assert触发的退出,其通常表明预期之外的错误,
        这通常是调用者的UB,如无UB的情况下触发此错误;也可能是LAMMP内部的逻辑错误,开发者期待的输入错误,
        在该逻辑处仅简单考虑了某些情况。如有此类错误,可以报告给开发者。此类型只会在定义了 
        LAMMP_DEBUG_ASSERT_CHECK 宏为 1 的情况下才会触发。

   3. PARAM_ASSERT_FAILURE (枚举值为3)为参数检查失败导致的退出,其通常表明调用者传入了无效的参数,
        导致函数的行为不符合预期。此类错误不可接受,会导致计算无法继续进行,导致程序崩溃。此类型的错误只有在
        定义了 LAMMP_DEBUG_PARAM_ASSERT_CHECK 宏为 1 的情况下才会触发。

   4. MEMORY_ALLOC_FAILURE (枚举值为4)为内存分配失败退出,这可能有两种情况:一种情况为分配了堆内存不足,
        导致程序崩溃;另一种情况为栈分配器的栈溢出(栈空间不足或其他UB),其中,情况一是会永远进行的,而情况二
        只有在定义了 LAMMP_DEBUG_STACK_OVERFLOW_CHECK 宏为 1 的情况下才会触发。

   5. MEMORY_FREE_FAILURE (枚举值为5)为内存释放错误,此错误有两种触发可能,一种为堆内存分配释放时,头部信息被损坏
        可能源于传入错误的指针,或缓冲区溢出导致此头部损坏。另一种情况为类似的,由栈分配器分配的内存释放时,头部信息损坏
        或指针不在栈的范围内,导致释放错误,如不是传入错误指针,则可能为栈分配的前一次内存缓冲区溢出,导致此内存释放时,
        头部信息损坏,导致释放无法进行。此类错误错误触发情况较为复杂,LAMMP_DEBUG_MEMORY_CHECK 宏为 1 时,两种情况都
        有可能发生,仅定义 LAMMP_DEBUG_STACK_OVERFLOW_CHECK 宏为 1 时,此错误仅可能由栈分配器触发。

   6. OUT_OF_BOUNDS (枚举值为6)为数组越界访问导致的退出,通常表明未按规定使用空间。此类型的错误在堆栈分配器中,
        均可能触发,但由于栈分配器的特殊性,可能部分越界访问可能被判定为栈溢出,或内存释放错误。具体可尝试查看错误信息。
        此类型只会在定义了 LAMMP_DEBUG_MEMORY_CHECK 宏为 1 的情况下才会触发,Release 模式下通常为 0 。

   7. MEMORY_LEAK (枚举值为7)为内存泄漏导致的退出,有两种情况,一种情况为堆内存计数器不为0,另一种情况为当前栈帧
        不在栈底。此类型的错误需定义 LAMMP_DEBUG_MEMORY_MEMORY_LEAK 宏为 1,才会触发。通常情况下,此错误需要手动调用
        lmmp_leak_tracker宏进行检查。但在调用堆分配器重置时,将会显式检查此时的堆计数器是否为0;在进行栈重置时,会显式检
        查栈是否为空,若不满足,触发此错误。特别注意,当手动调用检查宏时,在某些情况下,可能会进行一些全局堆资源的初始化,
        但未释放,如想正确计数,请先调用 lmmp_global_deinit 进行全局共享的堆资源的安全释放。

   8. UNEXPECTED_ERROR (枚举值为8)为其他未知错误导致的退出。
警告
LAMMP内部中断都将会调用此函数,如果全局退出函数为NULL,则使用默认的退出函数,会打印出全部错误信息,并调用 abort 函数中断程序。自定义全局退出函数请通过 lmmp_set_abort_fn 函数进行设置。请不要在全局退出函数里做任 何危险的操作,本库的开发者不对其调用产生的影响做任何保证。

在文件 abort.c42 行定义.

42 {
43 uintptr_t curr = atomic_load(&lmmp_abort_func);
45 if (fn != NULL) {
46 fn(type, msg, func, line);
47 } else {
48 fprintf(stderr, "LAMMP abort at [%s]:%d\n", func, line);
49 fprintf(stderr, "Abort type: %s, abort msg: \n%s\n", type_to_str(type), msg);
50 fflush(stderr);
51 abort();
52 }
53}
static const char * type_to_str(lmmp_error_t type)
Definition abort.c:19
static atomic_uintptr_t lmmp_abort_func
Definition abort.c:12
void(* lmmp_abort_fn)(lmmp_error_t type, const char *msg, const char *func, int line)
LAMMP 全局退出函数指针类型
Definition lmmp.h:150

引用了 lmmp_abort_func , 以及 type_to_str().

被这些函数引用 check_extra_memory_overflow(), check_memory_block_integrity(), lmmp_alloc_debug(), lmmp_chech_memory(), lmmp_leak_tracker(), lmmp_set_heap_allocator(), lmmp_stack_alloc(), lmmp_stack_free(), lmmp_stack_reset() , 以及 lmmp_temp_stack_alloc_().

+ 函数调用图:
+ 这是这个函数的调用关系图:

◆ lmmp_alloc()

void * lmmp_alloc ( size_t  size)

内存分配函数(调用lmmp_heap_alloc_fn)

参数
size要分配的内存字节数
注解
调用堆内存分配器,分配失败将触发 lmmp_abort
返回
返回指向分配内存的指针(分配失败不会 return NULL,而是直接触发 lmmp_abort)

在文件 memory.c166 行定义.

166 {
167 if (size) {
168 void* ret = heap_alloc_func(size);
169 if (ret == NULL)
170 lmmp_chech_memory(size, __func__, __LINE__);
171#if LAMMP_DEBUG_MEMORY_LEAK == 1
173#endif
174 return ret;
175 }
176 return NULL;
177}
#define heap_alloc_func
Definition memory.c:26
static _Thread_local int heap_alloc_count
Definition memory.c:30
static void lmmp_chech_memory(size_t size, const char *func, int line)
Definition memory.c:117

引用了 heap_alloc_count, heap_alloc_func , 以及 lmmp_chech_memory().

被这些函数引用 lmmp_fft_memstack_() , 以及 lmmp_strong_rng_init_().

+ 函数调用图:
+ 这是这个函数的调用关系图:

◆ lmmp_alloc_count()

int lmmp_alloc_count ( int  cnt)

堆内存分配计数器(线程局部)

参数
cnt若不为0,则将堆内存计数器置为cnt
返回
返回当前的heap分配计数(如果被设置,即返回旧的计数值),即目前未被释放的堆内存数量

在文件 memory.c123 行定义.

123 {
124 if (cnt != 0) {
125 int new_cnt = cnt;
126 cnt = heap_alloc_count;
127 heap_alloc_count = new_cnt;
128 return cnt;
129 }
130 return heap_alloc_count;
131}

引用了 heap_alloc_count.

◆ lmmp_free()

void lmmp_free ( void *  ptr)

内存释放函数(调用lmmp_heap_free_fn)

参数
ptr要释放的内存指针

在文件 memory.c204 行定义.

204 {
205 if (ptr) {
206 heap_free_func(ptr);
207#if LAMMP_DEBUG_MEMORY_LEAK == 1
209#endif
210 }
211}
#define heap_free_func
Definition memory.c:27

引用了 heap_alloc_count , 以及 heap_free_func.

被这些函数引用 lmmp_fft_memstack_(), lmmp_limb_elem_mul_(), lmmp_mul_fft_(), lmmp_mul_fft_cache_(), lmmp_mul_fft_unbalance_(), lmmp_mullo_fft_(), lmmp_num_heap_free_(), lmmp_num_heap_mul_(), lmmp_prime_cache_free_(), lmmp_prime_int_table_free_(), lmmp_strong_rng_free_(), lmmp_trialdiv_short_() , 以及 lmmp_vec_elem_mul_().

+ 这是这个函数的调用关系图:

◆ lmmp_global_deinit()

void lmmp_global_deinit ( void  )

(线程局部的)全局共享的动态分配的堆内存资源释放函数

注解
调用此函数将释放全局范围内的所有动态分配的堆内存资源。 此函数可重入,多次调用不会导致重复释放。如需要再次使用,请重新调用 lmmp_global_init 初始化。 部分惰性初始化的资源将在再次首次使用时再次初始化,调用此函数可能导致部分缓存失效,导致性能下降。
警告
我们建议在线程结束时或程序进程结束时调用此函数。多线程下,每个线程都会拥有独立的副本, 未调用此函数结束线程可能导致内存泄漏。

在文件 memory.c406 行定义.

406 {
409}
void lmmp_stack_reset(size_t size)
LAMMP 全局栈重置函数(通常不需要手动调用)
Definition memory.c:39
void lmmp_prime_int_table_free_(void)
释放全局素数表

引用了 lmmp_prime_int_table_free_() , 以及 lmmp_stack_reset().

被这些函数引用 lmmp_set_heap_allocator().

+ 函数调用图:
+ 这是这个函数的调用关系图:

◆ lmmp_global_init()

void lmmp_global_init ( void  )

全局初始化函数(线程局部的)

注解
调用此函数将初始化全局范围内的所有线程局部资源,如栈式分配器等。 部分惰性初始化的资源将在首次使用时初始化。调用此函数不会进行初始化。 此函数可重入,多次调用不会导致重复初始化。
警告
我们建议在进程或线程启动时调用此函数,以保证线程安全。

在文件 memory.c402 行定义.

402 {
404}
void lmmp_stack_init(void)
LAMMP 全局栈初始化函数(通常不需要手动调用)
Definition memory.c:66

引用了 lmmp_stack_init().

被这些函数引用 lmmp_set_heap_allocator().

+ 函数调用图:
+ 这是这个函数的调用关系图:

◆ lmmp_leak_tracker()

void lmmp_leak_tracker ( const char *  func,
int  line 
)

内存泄漏检测器

参数
func泄漏发生的函数名
line泄漏发生的行号
警告
内存计数器均是线程局部的,仅会检测单线程的内存泄漏。
注解
将会同时检验堆内存和栈内存,若堆内存计数器不为0,或栈内存的栈顶不在栈底,都会触发lmmp_abort 两者同时发生则将输出两者的信息。

在文件 memory.c133 行定义.

133 {
134 char msg[192] = {0};
135 int offset = 0;
136 const int max_len = sizeof(msg) - 1;
137 int t = 0;
138 if (heap_alloc_count != 0) {
139 offset +=
140 snprintf(msg + offset, max_len - offset, "Heap allocations not freed: %d block(s)\n", heap_alloc_count);
141 t = 1;
142 }
144 offset += snprintf(msg + offset, max_len - offset,
145 "Default stack allocator is not empty. top: %p, begin: %p, end: %p\n",
147 t = 1;
148 }
149 if (t) {
150 lmmp_abort(LAMMP_ERROR_MEMORY_LEAK, msg, func, line);
151 }
152}
void lmmp_abort(lmmp_error_t type, const char *msg, const char *func, int line)
LAMMP 全局退出函数,内部错误或断言失败时调用,若设置了全局退出函数,则会调用该函数,否则会调用默认的退出函数。
Definition abort.c:42
_Thread_local void * lmmp_stack_begin
Definition memory.c:32
_Thread_local void * lmmp_stack_top
Definition memory.c:34
_Thread_local void * lmmp_stack_end
Definition memory.c:33

引用了 heap_alloc_count, LAMMP_ERROR_MEMORY_LEAK, lmmp_abort(), lmmp_stack_begin, lmmp_stack_end , 以及 lmmp_stack_top.

+ 函数调用图:

◆ lmmp_realloc()

void * lmmp_realloc ( void *  ptr,
size_t  size 
)

内存重分配函数(调用lmmp_realloc_fn)

参数
ptr已分配的内存指针
size新的内存大小(字节)
注解
调用堆内存重新分配器,分配失败将触发 lmmp_abort
返回
成功返回指向新内存区域的指针(分配失败不会 return NULL,而是直接触发 lmmp_abort)

在文件 memory.c186 行定义.

186 {
187 void* ret = realloc_func(oldptr, new_size);
188 if (ret == NULL)
189 lmmp_chech_memory(new_size, __func__, __LINE__);
190 return ret;
191}
#define realloc_func
Definition memory.c:28

引用了 lmmp_chech_memory() , 以及 realloc_func.

被这些函数引用 lmmp_strong_rng_extern_().

+ 函数调用图:
+ 这是这个函数的调用关系图:

◆ lmmp_set_abort_fn()

lmmp_abort_fn lmmp_set_abort_fn ( lmmp_abort_fn  func)

设置 LAMMP 全局退出函数(所有线程均生效)

参数
func退出函数指针,可以为NULL
警告
请注意,我们将不会对 func 的调用做任何保护,因此请不要在 func 里做任何危险的操作, 本库的开发者不对 func 函数的调用产生的影响做任何保证。
注解
若 func 为 NULL,则代表使用默认的退出机制。同时,此函数指针是全局的,所有线程共享。
返回
返回之前的退出函数指针,若原指针为NULL,则返回NULL。

在文件 abort.c14 行定义.

14 {
15 uintptr_t old = atomic_exchange(&lmmp_abort_func, (uintptr_t)func);
16 return (lmmp_abort_fn)old;
17}

引用了 lmmp_abort_func.

◆ lmmp_set_heap_allocator()

void lmmp_set_heap_allocator ( const lmmp_heap_allocator_t heap)

设置 LAMMP 全局堆内存分配函数

参数
heap新的堆内存分配器,可以为NULL,表示使用默认的 malloc, free, realloc
警告
由于所有共享内存都采用堆内存分配。因此,传入新的堆分配器将会首先调用 lmmp_global_deinit 函数,释放所有共享内存,以保证老旧的堆资源被释放。 然后将会自动调用 lmmp_global_init 函数,重新分配所有线程局部内存。 同时,为保证内存不泄露,在开启 LAMMP_DEBUG_MEMORY_LEAK 宏时,将会对堆 栈分配器进行检查。若此时堆栈分配计数器不为 0,则会触发lmmp_abort函数, 并输出相应的错误信息。
注解
堆分配器是线程局部的,因此,创建新线程时,如有需要,请自行设置新的堆分配器。 同时也请自行保证分配器和释放器相匹配。

在文件 memory.c76 行定义.

76 {
77 if (heap == NULL)
78 return;
80#if LAMMP_DEBUG_MEMORY_LEAK == 1
81 if (heap_alloc_count != 0) {
82 char msg[64];
83 snprintf(msg, sizeof(msg), "Older heap allocations not freed: %d block(s)", heap_alloc_count);
84 lmmp_abort(LAMMP_ERROR_MEMORY_LEAK, msg, __func__, __LINE__);
85 }
86#endif
87 global_heap = *heap;
89}
void lmmp_global_init(void)
全局初始化函数(线程局部的)
Definition memory.c:402
void lmmp_global_deinit(void)
(线程局部的)全局共享的动态分配的堆内存资源释放函数
Definition memory.c:406
static _Thread_local lmmp_heap_allocator_t global_heap
Definition memory.c:20

引用了 global_heap, heap_alloc_count, LAMMP_ERROR_MEMORY_LEAK, lmmp_abort(), lmmp_global_deinit() , 以及 lmmp_global_init().

+ 函数调用图:

◆ lmmp_stack_alloc()

void * lmmp_stack_alloc ( size_t  size)

栈内存分配函数(使用stack_get_top和stack_set_top)

参数
size要分配的内存字节数
警告
请严格按照分配顺序的逆序释放内存,否则会导致未定义行为或导致栈溢出触发lmmp_abort 且严禁用于分配持久内存,如全局变量等。
返回
成功返回指向分配内存的指针,栈溢出时,会触发lmmp_abort

在文件 memory.c218 行定义.

218 {
219 if (size == 0) {
220 return NULL;
221 }
222 size_t total_size = SIZE_SIZE + LMMP_ROUND_UP_MULTIPLE(size, LAMMP_MAX_ALIGN);
223 void* old_top = stack_get_top_func();
224 void* new_top = (mp_byte_t*)old_top + total_size;
225#if LAMMP_DEBUG_STACK_OVERFLOW_CHECK == 1
226 if (new_top > lmmp_stack_end) {
227 char msg[128];
228 snprintf(msg, sizeof(msg), "Stack overflow (trying to allocate: %zu bytes, stack remaining: %zu bytes)",
229 total_size, (size_t)((mp_byte_t*)lmmp_stack_end - (mp_byte_t*)old_top));
230 lmmp_abort(LAMMP_ERROR_MEMORY_ALLOC_FAILURE, msg, __func__, __LINE__);
231 }
232#endif // LAMMP_DEBUG_STACK_OVERFLOW_CHECK == 1
233 stack_set_top_func(new_top);
234 *(size_t*)old_top = total_size;
235 return (mp_byte_t*)old_top + SIZE_SIZE;
236}
uint8_t mp_byte_t
Definition lmmp.h:210
#define LAMMP_MAX_ALIGN
Definition lmmp.h:219
#define LMMP_ROUND_UP_MULTIPLE(a, m)
Definition lmmp.h:361
#define stack_set_top_func(top)
Definition memory.c:37
#define stack_get_top_func()
Definition memory.c:36
#define SIZE_SIZE
Definition memory.c:216

引用了 LAMMP_ERROR_MEMORY_ALLOC_FAILURE, LAMMP_MAX_ALIGN, lmmp_abort(), LMMP_ROUND_UP_MULTIPLE, lmmp_stack_end, SIZE_SIZE, stack_get_top_func , 以及 stack_set_top_func.

+ 函数调用图:

◆ lmmp_stack_free()

void lmmp_stack_free ( void *  ptr)

栈内存释放函数(使用stack_get_top和stack_set_top)

参数
ptr要释放的内存指针
警告
请严格按照分配顺序的逆序释放内存(后分配者先释放)

在文件 memory.c238 行定义.

238 {
239 if (ptr == NULL) {
240 return;
241 }
242#if LAMMP_DEBUG_STACK_OVERFLOW_CHECK == 1
243 if (ptr < lmmp_stack_begin || ptr >= lmmp_stack_end) {
244 char msg[128];
245 snprintf(msg, sizeof(msg), "Invalid stack pointer (trying to free: %p ; stack start: %p , stack end: %p )", ptr,
247 lmmp_abort(LAMMP_ERROR_MEMORY_FREE_FAILURE, msg, __func__, __LINE__);
248 }
249#endif // LAMMP_DEBUG_STACK_OVERFLOW_CHECK == 1
250 void* old_top = stack_get_top_func();
251 size_t total_size = *(size_t*)((mp_byte_t*)ptr - SIZE_SIZE);
252 void* new_top = (mp_byte_t*)old_top - total_size;
253#if LAMMP_DEBUG_STACK_OVERFLOW_CHECK == 1
254 if (new_top < lmmp_stack_begin || new_top > lmmp_stack_end) {
255 char msg[256];
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.");
260 lmmp_abort(LAMMP_ERROR_MEMORY_FREE_FAILURE, msg, __func__, __LINE__);
261 }
262#endif // LAMMP_DEBUG_STACK_OVERFLOW_CHECK == 1
263 stack_set_top_func(new_top);
264}

引用了 LAMMP_ERROR_MEMORY_FREE_FAILURE, lmmp_abort(), lmmp_stack_begin, lmmp_stack_end, SIZE_SIZE, stack_get_top_func , 以及 stack_set_top_func.

+ 函数调用图:

◆ lmmp_stack_init()

void lmmp_stack_init ( void  )

LAMMP 全局栈初始化函数(通常不需要手动调用)

注解
按照默认的栈大小(320kb),对栈进行初始化,可多次重入。 lmmp_global_init 函数会自动调用此函数,无需手动调用。

在文件 memory.c66 行定义.

66 {
67 if (lmmp_stack_begin != NULL) {
68 return;
69 } else {
73 }
74}
#define LAMMP_DEFAULT_STACK_SIZE
Definition mparam.h:23

引用了 heap_alloc_func, LAMMP_DEFAULT_STACK_SIZE, lmmp_stack_begin, lmmp_stack_end , 以及 lmmp_stack_top.

被这些函数引用 lmmp_global_init().

+ 这是这个函数的调用关系图:

◆ lmmp_stack_reset()

void lmmp_stack_reset ( size_t  size)

LAMMP 全局栈重置函数(通常不需要手动调用)

参数
size新的默认栈大小,单位为字节(不建议设置少于 256KB 的栈,少于此值可能导致栈溢出)
警告
请注意调用此函数后,访问之前的分配的栈空间将会导致未定义行为。在定义了 LAMMP_DEBUG_MEMORY_LEAK 宏时,释放默认栈时,会检查默认栈是否为空, 若默认栈不为空,则会触发lmmp_abort函数。栈为空时,或者无法确定栈是否初始化, 均可以调用此函数,如果设置的大小比此前的大小小,则会直接重置栈顶,否则,会重新分 配一块新的栈内存。同时,为保证内存不泄露,请自行确保调用此函数时,栈为空。 在开启 LAMMP_DEBUG_MEMORY_LEAK 宏时,将会对栈进行检查。若此时栈不为空, 则会触发lmmp_abort函数。
注解
当 size 为 0 时,将会释放栈,如果此后再使用栈内存。

在文件 memory.c39 行定义.

39 {
40 if (size) {
44 }
45 if (lmmp_stack_begin == NULL) {
46 lmmp_abort(LAMMP_ERROR_MEMORY_ALLOC_FAILURE, "Default stack allocation failed", __func__, __LINE__);
47 }
49 } else {
50#if LAMMP_DEBUG_MEMORY_LEAK == 1
52 char msg[128];
53 snprintf(msg, sizeof(msg), "Default stack allocator is not empty. top: %p, begin: %p, end: %p\n",
55 lmmp_abort(LAMMP_ERROR_MEMORY_LEAK, msg, __func__, __LINE__);
56 }
57#endif
60 lmmp_stack_begin = NULL;
61 lmmp_stack_end = NULL;
62 lmmp_stack_top = NULL;
63 }
64}

引用了 heap_free_func, LAMMP_ERROR_MEMORY_ALLOC_FAILURE, LAMMP_ERROR_MEMORY_LEAK, lmmp_abort(), lmmp_stack_begin, lmmp_stack_end, lmmp_stack_top , 以及 realloc_func.

被这些函数引用 lmmp_global_deinit().

+ 函数调用图:
+ 这是这个函数的调用关系图: