From ea64e4ac763777cbcc7c5846eebd884d8af6b4c9 Mon Sep 17 00:00:00 2001 From: weiwenhao <1101140857@qq.com> Date: Fri, 22 Sep 2023 19:12:23 +0800 Subject: [PATCH] fix: memory overflow (#28) * temp: find overflow * temp: parker cannot test pass * fix: args->length + 1 not wrapped in brackets --- runtime/allocator.c | 53 +++++++++++++++++--- runtime/collector.c | 7 +-- runtime/memory.c | 13 +++-- runtime/memory.h | 2 + runtime/nutils/array.h | 4 +- runtime/nutils/hash.h | 9 +++- runtime/nutils/map.c | 2 + runtime/nutils/set.c | 1 + runtime/nutils/string.c | 5 ++ runtime/nutils/syscall.c | 10 ++-- runtime/nutils/vec.c | 1 + runtime/runtime.c | 8 ++- src/ssa.c | 24 +++++---- tests/blackbox/20230922_00_for.c | 15 ++++++ tests/blackbox/cases/20230922_00_for.n | 6 +++ tests/blackbox/cases/parker | 2 +- utils/autobuf.c | 2 +- utils/bitmap.c | 1 + utils/ct_list.c | 3 +- utils/error.c | 2 +- utils/exec.c | 2 +- utils/helper.h | 67 +++++++++++++++----------- utils/linked.c | 3 +- utils/slice.c | 9 ++-- utils/stack.c | 4 +- utils/table.c | 9 ++-- utils/table.h | 2 +- utils/type.c | 46 ++++++++++++------ 28 files changed, 215 insertions(+), 97 deletions(-) create mode 100644 tests/blackbox/20230922_00_for.c create mode 100644 tests/blackbox/cases/20230922_00_for.n diff --git a/runtime/allocator.c b/runtime/allocator.c index 2016d7ef..ffac40e9 100644 --- a/runtime/allocator.c +++ b/runtime/allocator.c @@ -40,29 +40,38 @@ static bool summary_find_continuous(uint8_t level, page_summary_t *summaries, ui uint64_t find_max = 0; for (uint64_t i = *start; i < *end; ++i) { page_summary_t s = summaries[i]; - find_max += s.start; + find_max += s.start; // 左侧 + 新的 s 的 start if (find_max >= pages_count) { - // 找到了 find = true; find_end = i; break; } + // 当前 chunk 中间存在更大的 max 区域, 此时从当前 chunk 开始从新计算 find_max if (s.max > find_max) { find_max = s.max; find_start = i; } + + // find max 超过了需求熟练 if (find_max >= pages_count) { - // 找到了 + // 找到了完整的空闲位置 find = true; find_end = i; break; } - // 目前的空间都不满足条件,判断当前空间是否是完整空闲,非完整的空闲,必须要中断了 + // 目前的空间都不满足条件,判断当前空间是否是整个空闲(s.end = max_pages_count 表示全空闲) + // 如果非完整的空闲,则会导致连续性中断, 此时从 s.end 从新开始计算 if (s.end != max_pages_count) { - find_start = i; - find_max = s.end; + if (s.end > 0) { + find_start = i; // 已经从 i 开始记录 + find_max = s.end; + } else { + // s.end == 0, 表示当前 chunk 完全不可用,此时充值 find_max, 并且更新 find_start 为下一个块 + find_start = i + 1; + find_max = 0; + } } } *start = find_start; @@ -307,6 +316,8 @@ static void chunks_set(addr_t base, uint64_t size, bool v) { bit_end = CHUNK_BITS_COUNT - 1; } + DEBUGF("[runtime.chunks_set] chunk index: %lu, chunk block base: %p, bit_start: %lu, bit_end: %lu", + index, (void *) chunk->blocks, bit_start, bit_end); for (uint64_t i = bit_start; i <= bit_end; ++i) { if (v) { bitmap_set((uint8_t *) chunk->blocks, i); @@ -353,6 +364,8 @@ static addr_t page_alloc_find(uint64_t pages_count) { } } + DEBUGF("[runtime.page_alloc_find] find continuous pages, start: %lu, end: %lu", start, end); + // start ~ end 指向的一组 chunks 中包含连续的内存空间,现在需要确认起起点位置(假设 start == end, 其 可能是 start or mid or end 中的任意一个位置) addr_t find_addr = 0; if (start == end) { @@ -378,12 +391,18 @@ static addr_t page_alloc_find(uint64_t pages_count) { // 计算 find_addr find_addr = chunk_base(start) + bit_start * ALLOC_PAGE_SIZE; + DEBUGF("[runtime.page_alloc_find] find addr=%p, start == end, start: %lu, chunk_base: %p, bit start: %lu, bit end: %lu", + (void *) find_addr, start, chunk->blocks, bit_start, bit_end); + // 更新从 find_addr 对应的 bit ~ page_count 位置的所有 chunk 的 bit 为 1 } else { - // 跨越多个块 + // start ~ end 这一段连续的内存空间跨越多个 chunk page_summary_t *l5_summaries = page_alloc->summary[PAGE_SUMMARY_LEVEL - 1]; page_summary_t start_summary = l5_summaries[start]; uint64_t bit_start = CHUNK_BITS_COUNT + 1 - start_summary.end; + DEBUGF("[runtime.page_alloc_find] find addr=%p, start != end, start chunk: %lu, chunk summary [%d, %d, %d]," + " end: %lu, bit start: %lu", + (void *) find_addr, start, start_summary.start, start_summary.max, start_summary.end, end, bit_start); find_addr = chunk_base(start) + bit_start * ALLOC_PAGE_SIZE; } assertf(find_addr % ALLOC_PAGE_SIZE == 0, "find addr=%p not align_up", find_addr); @@ -391,6 +410,9 @@ static addr_t page_alloc_find(uint64_t pages_count) { // 更新相关的 chunks 为使用状态 chunks_set(find_addr, pages_count * ALLOC_PAGE_SIZE, 1); + DEBUGF("[runtime.page_alloc_find] find_addr: %p, page_count: %lu, size: %lu", + (void *) find_addr, pages_count, pages_count * ALLOC_PAGE_SIZE); + return find_addr; } @@ -442,6 +464,7 @@ void *mheap_sys_alloc(mheap_t *mheap, uint64_t *size) { void *v = NULL; while (true) { + allocated_total_bytes += alloc_size; v = sys_memory_map((void *) hint->addr, alloc_size); if (v == (void *) hint->addr) { // 分配成功, 定义下一个分配点,基于此可以获得 64MB 对齐的内存地址 @@ -465,6 +488,9 @@ void *mheap_sys_alloc(mheap_t *mheap, uint64_t *size) { slice_push(mheap->arena_indexes, (void *) i); } + // 虚拟内存映射并不会真的写入到内存,必须触发内存页中断才行 + DEBUGF("[mheap_sys_alloc] allocate_total_bytes=%lu", allocated_total_bytes); + *size = alloc_size; return v; } @@ -638,9 +664,12 @@ static mspan_t *mcache_refill(mcache_t *mcache, uint64_t spanclass) { uncache_span(mcentral, mspan); } - // cache + // 从 mcentral 中读取一个 span 进行读取 mspan = cache_span(mcentral); mcache->alloc[spanclass] = mspan; + DEBUGF("[runtime.mcache_refill] mcentral=%p, spanclass=%lu|%d, mspan_base=%p - %p, obj_size=%lu, alloc_count=%lu", + mcentral, spanclass, mspan->spanclass, (void *) mspan->base, (void *) mspan->end, mspan->obj_size, + mspan->alloc_count); return mspan; } @@ -824,7 +853,15 @@ void mheap_free_span(mheap_t *mheap, mspan_t *span) { // arena.bits 保存了当前 span 中的指针 bit, 当下一次当前内存被分配时会覆盖写入 // 垃圾回收期间不会有任何指针指向该空间,因为当前 span 就是因为没有被任何 ptr 指向才被回收的 + remove_total_bytes += span->pages_count * ALLOC_PAGE_SIZE; + // 将物理内存归还给操作系统 + DEBUGF("[runtime.mheap_free_span] remove_total_bytes=%lu MB, span.base=0x%lx, span.pages_count=%ld, remove_size=%lu", + remove_total_bytes / 1024 / 1024, + span->base, + span->pages_count, + span->pages_count * ALLOC_PAGE_SIZE); + sys_memory_remove((void *) span->base, span->pages_count * ALLOC_PAGE_SIZE); } diff --git a/runtime/collector.c b/runtime/collector.c index 07fce8af..bd0897c0 100644 --- a/runtime/collector.c +++ b/runtime/collector.c @@ -267,14 +267,9 @@ static void sweep_span(linked_t *full, linked_t *partial, mspan_t *span) { // 内存回收(未返回到堆) allocated_bytes -= span->obj_size; -#ifdef DEBUG DEBUGF("[runtime.sweep_span] success, span->class=%d, span->base=0x%lx, span->obj_size=%ld, obj_addr=0x%lx, allocator_bytes=%ld", span->spanclass, span->base, span->obj_size, span->base + i * span->obj_size, allocated_bytes); - // 将对应位置的内存设置为 0 - memset((void *) (span->base + i * span->obj_size), 0, span->obj_size); -#endif - } } @@ -287,7 +282,7 @@ static void sweep_span(linked_t *full, linked_t *partial, mspan_t *span) { span->alloc_count = bitmap_set_count(span->alloc_bits); if (span->alloc_count == 0) { - DEBUGF("span free to heap, base=0x%lx, class=%d", span->base, span->spanclass); + DEBUGF("[sweep_span] span free to heap, base=0x%lx, class=%d", span->base, span->spanclass); mheap_free_span(memory->mheap, span); free_mspan_meta(span); return; diff --git a/runtime/memory.c b/runtime/memory.c index f9be3ce9..0cd0d76a 100644 --- a/runtime/memory.c +++ b/runtime/memory.c @@ -1,11 +1,17 @@ #include "memory.h" +#include "stdlib.h" +uint64_t remove_total_bytes = 0; // 当前回收到物理内存中的总空间 +uint64_t allocated_total_bytes = 0; // 当前分配的总空间 uint64_t allocated_bytes = 0; // 当前分配的内存空间 uint64_t next_gc_bytes = 0; // 下一次 gc 的内存量 bool force_gc = 0; // runtime_judge_gc 总是立刻进行 gc rtype_t *rt_find_rtype(uint32_t rtype_hash) { - return table_get(rt_rtype_table, itoa(rtype_hash)); + char *str = itoa(rtype_hash); + rtype_t *result = table_get(rt_rtype_table, str); + free(str); + return result; } uint64_t rt_rtype_out_size(uint32_t rtype_hash) { @@ -82,8 +88,9 @@ void rtypes_deserialize() { } // rtype 已经组装完毕,现在加入到 rtype table 中 - table_set(rt_rtype_table, itoa(r->hash), r); - + char *str = itoa(r->hash); + table_set(rt_rtype_table, str, r); + free(str); } diff --git a/runtime/memory.h b/runtime/memory.h index 44d7f382..7e5f5833 100644 --- a/runtime/memory.h +++ b/runtime/memory.h @@ -55,6 +55,8 @@ #define DEFAULT_NEXT_GC_BYTES (100 * 1024) // 100KB #define NEXT_GC_FACTOR 2 +extern uint64_t remove_total_bytes; // 当前回收到物理内存中的总空间 +extern uint64_t allocated_total_bytes; // 当前分配的总空间 extern uint64_t allocated_bytes; // 当前分配的内存空间 extern uint64_t next_gc_bytes; // 下一次 gc 的内存量 extern bool force_gc; // runtime_judge_gc 总是立刻进行 gc diff --git a/runtime/nutils/array.h b/runtime/nutils/array.h index 9144e1eb..6f0764fe 100644 --- a/runtime/nutils/array.h +++ b/runtime/nutils/array.h @@ -24,11 +24,13 @@ static inline n_array_t *rt_array_new(rtype_t *element_rtype, uint64_t length) { addr, element_rtype->size, type_kind_str[element_rtype->kind], - element_rtype->last_ptr > 0, + element_rtype->last_ptr > 0, rtype.size, length, type_kind_str[rtype.kind]) + free(rtype.gc_bits); + return addr; } diff --git a/runtime/nutils/hash.h b/runtime/nutils/hash.h index 2db6700a..f7d3896d 100644 --- a/runtime/nutils/hash.h +++ b/runtime/nutils/hash.h @@ -43,14 +43,19 @@ static inline uint64_t extract_data_index(uint64_t hash_value) { static inline uint64_t key_hash(rtype_t *rtype, void *key_ref) { char *str = rtype_value_str(rtype, key_ref); - return hash_string(str); + uint64_t result = hash_string(str); + free((void *) str); + return result; } static inline bool key_equal(rtype_t *rtype, void *actual, void *expect) { DEBUGF("[key_equal] actual=%p, expect=%p", actual, expect) char *actual_str = rtype_value_str(rtype, actual); char *expect_str = rtype_value_str(rtype, expect); - return str_equal(actual_str, expect_str); + bool result = str_equal(actual_str, expect_str); + free((void *) actual_str); + free((void *) expect_str); + return result; } /** diff --git a/runtime/nutils/map.c b/runtime/nutils/map.c index 35ffca97..97c678e4 100644 --- a/runtime/nutils/map.c +++ b/runtime/nutils/map.c @@ -114,6 +114,7 @@ n_cptr_t map_access(n_map_t *m, void *key_ref) { return 0; } + free((void *) key_str); uint64_t data_index = get_data_index(m, hash_index); // 找到值所在中数组位置起始点并返回 @@ -144,6 +145,7 @@ n_cptr_t map_assign(n_map_t *m, void *key_ref) { key_rtype->kind, key_str, hash_index); + free((void *) key_str); uint64_t data_index = 0; if (hash_value_empty(hash_value)) { diff --git a/runtime/nutils/set.c b/runtime/nutils/set.c index add5028c..0a872b25 100644 --- a/runtime/nutils/set.c +++ b/runtime/nutils/set.c @@ -43,6 +43,7 @@ static void set_grow(n_set_t *m) { DEBUGF("[runtime.set_grow] len=%lu, cap=%lu, key_data=%p, hash_table=%p", m->length, m->capacity, m->key_data, m->hash_table); + assert(m->key_rtype_hash > 0); rtype_t *key_rtype = rt_find_rtype(m->key_rtype_hash); assertf(key_rtype, "cannot find key_rtype by hash %lu", m->key_rtype_hash); uint64_t key_size = rtype_out_size(key_rtype, POINTER_SIZE); diff --git a/runtime/nutils/string.c b/runtime/nutils/string.c index 476ae325..274a07db 100644 --- a/runtime/nutils/string.c +++ b/runtime/nutils/string.c @@ -44,6 +44,11 @@ n_string_t *string_new(void *raw_string, uint64_t length) { void *string_ref(n_string_t *n_str) { DEBUGF("[runtime.string_ref] length=%lu, data=%p", n_str->length, n_str->data); + // 空间足够,且最后一位已经是 0, 可以直接返回 + if (n_str->capacity > n_str->length && n_str->data[n_str->length] == '\0') { + return n_str->data; + } + // 结尾添加 '\0' 字符 int a = '\0'; vec_push(n_str, &a); diff --git a/runtime/nutils/syscall.c b/runtime/nutils/syscall.c index 08ba44b4..b948b549 100644 --- a/runtime/nutils/syscall.c +++ b/runtime/nutils/syscall.c @@ -22,12 +22,12 @@ void syscall_exec(n_string_t *path, n_vec_t *argv, n_vec_t *envp) { char *p_str = string_ref(path); // args 转换成 char* 格式并给到 execve - char **c_args = mallocz(sizeof(char *) * argv->length + 1); + char **c_args = mallocz(sizeof(char *) * (argv->length + 1)); for (int i = 0; i < argv->length; ++i) { n_string_t *arg; vec_access(argv, i, &arg); if (arg == NULL) { - return; + continue; } char *c_arg = string_ref(arg); @@ -36,15 +36,17 @@ void syscall_exec(n_string_t *path, n_vec_t *argv, n_vec_t *envp) { c_args[argv->length] = NULL; // 最后一个元素为 NULL // envs - char **c_envs = mallocz(sizeof(char *) * envp->length); + DEBUGF("[syscall_exec] envp->length=%lu", envp->length); + char **c_envs = mallocz(sizeof(char *) * (envp->length + 1)); for (int i = 0; i < envp->length; ++i) { n_string_t *env; vec_access(envp, i, &env); if (env == NULL) { - return; + continue; } char *c_env = string_ref(env); + DEBUGF("[syscall_exec] c_env=%p, data=%s, strlen=%lu", (void *) c_env, c_env, strlen(c_env)); c_envs[i] = c_env; } c_envs[envp->length] = NULL; diff --git a/runtime/nutils/vec.c b/runtime/nutils/vec.c index e5f18af8..a4b04bc5 100644 --- a/runtime/nutils/vec.c +++ b/runtime/nutils/vec.c @@ -89,6 +89,7 @@ void vec_assign(n_vec_t *l, uint64_t index, void *ref) { rtype_t *element_rtype = rt_find_rtype(l->element_rtype_hash); uint64_t element_size = rtype_out_size(element_rtype, POINTER_SIZE); + DEBUGF("[runtime.vec_assign] element_size=%lu", element_size); // 计算 offset uint64_t offset = rtype_out_size(element_rtype, POINTER_SIZE) * index; // (size unit byte) * index void *p = l->data + offset; diff --git a/runtime/runtime.c b/runtime/runtime.c index 7ecb1dfc..944095b3 100644 --- a/runtime/runtime.c +++ b/runtime/runtime.c @@ -26,7 +26,13 @@ char *rtype_value_str(rtype_t *rtype, void *data_ref) { if (rtype->kind == TYPE_STRING) { n_string_t *n_str = (void *) fetch_addr_value((addr_t) data_ref); // 读取栈中存储的值 assertf(n_str && n_str->length > 0, "fetch addr by data ref '%p' err", data_ref); - return (char *) string_ref(n_str); + +// return strdup(string_ref(n_str)); + // 进行 data copy, 避免被 free + char *str = mallocz(n_str->length + 1); + memmove(str, n_str->data, n_str->length); + str[n_str->length] = '\0'; + return str; } assertf(false, "not support kind=%s", type_kind_str[rtype->kind]); diff --git a/src/ssa.c b/src/ssa.c index 169d4a01..081812be 100644 --- a/src/ssa.c +++ b/src/ssa.c @@ -31,19 +31,25 @@ static bool self_is_imm_dom(slice_t *be_doms, basic_block_t *self, uint64_t awai /** * 计算 block 中的直接支配者 - * @param be_doms - * @param block + * @param doms + * @param self * @return */ -static basic_block_t *calc_imm_domer(slice_t *be_doms, basic_block_t *await) { - for (int i = 0; i < be_doms->count; ++i) { - basic_block_t *self = be_doms->take[i]; +static basic_block_t *calc_imm_domer(slice_t *doms, basic_block_t *self) { + for (int i = 0; i < doms->count; ++i) { + basic_block_t *dom = doms->take[i]; + + // self 不能作为自己的的最近支配节点 + if (dom->id == self->id) { + continue; + } + // 判断 item 是否被除了 [await->id 和 self->id 以外的所有 id 所支配] - if (self_is_imm_dom(be_doms, self, await->id)) { - return self; + if (self_is_imm_dom(doms, dom, self->id)) { + return dom; } } - assertf(false, "block=%s must have one imm dom", await->name); + assertf(false, "block=%s must have one imm dom", self->name); exit(1); } @@ -121,7 +127,7 @@ void ssa_domers(closure_t *c) { /** * 计算最近支配点 * 在支配 p 的点中,若一个支配点 i (i != p), i 被 p 剩下其他的所有的支配点支配,则称 i 为 p 的最近支配点 imm_domer - * B0 没有 imm_domer + * B0 没有 imm_domer, 其他所有节点至少一个一个除了自身意外的最小支配者! * imm_domer 一定是父节点中的某一个 * @param c */ diff --git a/tests/blackbox/20230922_00_for.c b/tests/blackbox/20230922_00_for.c new file mode 100644 index 00000000..17ed8207 --- /dev/null +++ b/tests/blackbox/20230922_00_for.c @@ -0,0 +1,15 @@ +#include "tests/test.h" +#include "utils/assertf.h" +#include "utils/exec.h" +#include + +static void test_basic() { +// char *raw = exec_output(); +// printf("%s", raw); + +// assert_string_equal(raw, "hello world 2022 724 11.550000 ! ! !\n"); +} + +int main(void) { + TEST_BASIC +} \ No newline at end of file diff --git a/tests/blackbox/cases/20230922_00_for.n b/tests/blackbox/cases/20230922_00_for.n new file mode 100644 index 00000000..7712e931 --- /dev/null +++ b/tests/blackbox/cases/20230922_00_for.n @@ -0,0 +1,6 @@ +import libc_temp +import syscall + +for true { + usleep(10000) +} \ No newline at end of file diff --git a/tests/blackbox/cases/parker b/tests/blackbox/cases/parker index 8da4aabd..07af2b4c 160000 --- a/tests/blackbox/cases/parker +++ b/tests/blackbox/cases/parker @@ -1 +1 @@ -Subproject commit 8da4aabd0d4c78b7750a1667c461be16f3e5f222 +Subproject commit 07af2b4ce0661a870d804b108b621720d3481c16 diff --git a/utils/autobuf.c b/utils/autobuf.c index 7a19e2ab..f9d1718d 100644 --- a/utils/autobuf.c +++ b/utils/autobuf.c @@ -5,7 +5,7 @@ autobuf_t *autobuf_new(uint64_t cap) { autobuf_t *buf = NEW(autobuf_t); assertf(buf, "Memory allocation for autobuf_t failed"); - buf->data = malloc(cap); + buf->data = mallocz(cap); assertf(buf->data, "Memory allocation for autobuf_t failed"); buf->len = 0; // Initially, the length is zero diff --git a/utils/bitmap.c b/utils/bitmap.c index 93a7c86a..db4c43e7 100644 --- a/utils/bitmap.c +++ b/utils/bitmap.c @@ -42,6 +42,7 @@ int bitmap_set_count(bitmap_t *b) { } char *bitmap_to_str(uint8_t *bits, uint64_t count) { + return ""; // TODO char *result = mallocz(count + 1); for (int i = 0; i < count; ++i) { if (bitmap_test(bits, i)) { diff --git a/utils/ct_list.c b/utils/ct_list.c index 379e3783..c137df83 100644 --- a/utils/ct_list.c +++ b/utils/ct_list.c @@ -1,5 +1,6 @@ #include "ct_list.h" #include "assertf.h" +#include "helper.h" void ct_list_grow(list_t *l) { l->capacity = l->capacity * 2; @@ -11,7 +12,7 @@ list_t *ct_list_new(uint64_t element_size) { list->element_size = element_size; list->length = 0; list->capacity = VEC_DEFAULT_CAPACITY; - list->take = malloc(list->capacity * element_size); + list->take = mallocz(list->capacity * element_size); return list; } diff --git a/utils/error.c b/utils/error.c index 1f4b3c44..54739af6 100644 --- a/utils/error.c +++ b/utils/error.c @@ -8,7 +8,7 @@ // exit(code); // // va_list args; -// char *buf = malloc(sizeof(char) * ERROR_STR_COUNT); +// char *buf = mallocz(sizeof(char) * ERROR_STR_COUNT); // va_start(args, format); // vsprintf(buf, format, args); // va_end(args); diff --git a/utils/exec.c b/utils/exec.c index 08122dda..f22d5838 100644 --- a/utils/exec.c +++ b/utils/exec.c @@ -109,7 +109,7 @@ char *command_output(const char *work_dir, const char *command) { char buffer[128]; size_t size = 0; size_t capacity = 128; - result = (char *) malloc(capacity * sizeof(char)); + result = (char *) mallocz(capacity * sizeof(char)); if (!result) { perror("malloc"); pclose(pipe); diff --git a/utils/helper.h b/utils/helper.h index ec5f1eae..a5f89e48 100644 --- a/utils/helper.h +++ b/utils/helper.h @@ -14,6 +14,7 @@ #include #include "assertf.h" +#include "errno.h" #define string char * #define STRING_EOF '\0' @@ -23,14 +24,23 @@ #define v_addr_t uint64_t #define addr_t uint64_t -static inline void *mallocz(size_t size) { - void *ptr; - ptr = malloc(size); - if (size) { - memset(ptr, 0, size); - } - return ptr; -} +#define TDEBUGF(...) printf(__VA_ARGS__);printf("\n"); fflush(stdout); + +#undef free +#define free(ptr) ({ \ + if (ptr) { \ + free(ptr); \ + } \ +}) + + +#define mallocz(size) ({ \ + void *_ptr = malloc(size); \ + if (size) { \ + memset(_ptr, 0, size); \ + } \ + _ptr; \ +}) #define GROW_CAPACITY(capacity) \ ((capacity) < 8 ? 8 : (capacity)*2) @@ -42,7 +52,6 @@ static inline void *mallocz(size_t size) { //#define DEBUG_PARSER 1 //#define DEBUG 1 -#define TDEBUGF(...) printf(__VA_ARGS__);printf("\n"); fflush(stdout); #ifdef DEBUG #define DEBUGF(...) printf(__VA_ARGS__);printf("\n"); fflush(stdout); @@ -52,7 +61,7 @@ static inline void *mallocz(size_t size) { #define COPY_NEW(_type, src) ({ \ - _type *dst = malloc(sizeof(_type)); \ + _type *dst = mallocz(sizeof(_type)); \ memcpy(dst, src, sizeof(_type)); \ dst; \ }) @@ -137,16 +146,6 @@ static inline char *dsprintf(char *format, ...) { return realloc(buf, count + 1); } -static inline char *fixed_sprintf(char *format, ...) { - char *buf = mallocz(2000); - va_list args; - va_start(args, format); - int count = vsprintf(buf, format, args); - va_end(args); - - return realloc(buf, count + 1); -} - static inline int64_t max(int64_t a, int64_t b) { if (a > b) { return a; @@ -169,7 +168,7 @@ static inline char *itoa(int64_t n) { static inline char *utoa(uint64_t n) { int length = snprintf(NULL, 0, "%lu", n); - char *str = malloc(length + 1); + char *str = mallocz(length + 1); snprintf(str, length + 1, "%lu", n); return str; @@ -185,11 +184,21 @@ static int inline check_open(char *filepath, int flag) { return fd; } -static inline char *str_connect(char *a, char *b) { +static inline char *str_connect_free(char *a, char *b) { size_t dst_len = strlen(a); size_t src_len = strlen(b); char *buf = malloc(dst_len + src_len + 1); sprintf(buf, "%s%s", a, b); + free(a); + free(b); + return buf; +} + +static inline char *str_connect(char *a, char *b) { + size_t dst_len = strlen(a); + size_t src_len = strlen(b); + char *buf = mallocz(dst_len + src_len + 1); + sprintf(buf, "%s%s", a, b); return buf; } @@ -225,7 +234,7 @@ static inline char *file_read(char *path) { size_t fileSize = ftell(file); rewind(file); - char *buffer = (char *) malloc(fileSize + 1); + char *buffer = (char *) mallocz(fileSize + 1); if (buffer == NULL) { fprintf(stderr, "Not enough memory to read \"%s\".\n", path); exit(74); @@ -326,7 +335,7 @@ static inline char *ltrim(char *str, char *sub) { size_t res_len = len - count * sub_len + 1; // Allocate memory for the resulting trimmed string - char *res = malloc(res_len); + char *res = mallocz(res_len); // Copy the characters after the leading occurrences of the substring to the result memcpy(res, str + count * sub_len, res_len - 1); @@ -339,7 +348,7 @@ static inline char *ltrim(char *str, char *sub) { static inline char *get_workdir() { int size = 256; - char *buf = malloc(size); + char *buf = mallocz(size); VOID getcwd(buf, size); return buf; } @@ -426,7 +435,7 @@ static inline char *str_replace(char *str, char *old, char *new) { ins = tmp + len_rep; } - tmp = result = malloc(strlen(str) + (len_with - len_rep) * count + 1); + tmp = result = mallocz(strlen(str) + (len_with - len_rep) * count + 1); if (!result) return NULL; @@ -465,7 +474,7 @@ static inline void sys_memory_unmap(void *base, uint64_t size) { #ifdef __LINUX static inline void sys_memory_remove(void *addr, uint64_t size) { - madvise(addr, size, MADV_REMOVE); + madvise(addr, size, MADV_DONTNEED); } #else @@ -477,7 +486,7 @@ static inline void sys_memory_remove(void *addr, uint64_t size) { #endif static inline int64_t *take_numbers(char *str, uint64_t count) { - int64_t *numbers = malloc(count * sizeof(int64_t)); + int64_t *numbers = mallocz(count * sizeof(int64_t)); int i = 0; char *token; token = strtok(str, "\n"); @@ -495,7 +504,7 @@ static inline char *homedir() { } static inline char *fullpath(char *rel) { - char *path = (char *) malloc(PATH_MAX * sizeof(char)); + char *path = (char *) mallocz(PATH_MAX * sizeof(char)); if (!realpath(rel, path)) { return NULL; } diff --git a/utils/linked.c b/utils/linked.c index b706e237..5cdcfb02 100644 --- a/utils/linked.c +++ b/utils/linked.c @@ -10,7 +10,7 @@ static uint16_t linked_count(linked_t *l) { } linked_t *linked_new() { - linked_t *l = malloc(sizeof(linked_t)); + linked_t *l = mallocz(sizeof(linked_t)); l->count = 0; linked_node *empty = linked_new_node(); @@ -232,6 +232,7 @@ void linked_free(linked_t *l) { while (l->count > 0) { linked_pop_free(l); } + // 清理 empty_node free(l->front); diff --git a/utils/slice.c b/utils/slice.c index 136a4871..270e05f3 100644 --- a/utils/slice.c +++ b/utils/slice.c @@ -1,19 +1,20 @@ #include #include "slice.h" #include "stdlib.h" +#include "helper.h" slice_t *slice_new() { - slice_t *s = malloc(sizeof(slice_t)); + slice_t *s = mallocz(sizeof(slice_t)); s->count = 0; - s->take = malloc(sizeof(void *) * 8); + s->take = mallocz(sizeof(void *) * 8); s->capacity = 8; return s; } slice_t *slice_capacity_new(int capacity) { - slice_t *s = malloc(sizeof(slice_t)); + slice_t *s = mallocz(sizeof(slice_t)); s->count = 0; - s->take = malloc(sizeof(void *) * capacity); + s->take = mallocz(sizeof(void *) * capacity); s->capacity = capacity; return s; } diff --git a/utils/stack.c b/utils/stack.c index 8166c39e..255bb569 100644 --- a/utils/stack.c +++ b/utils/stack.c @@ -1,7 +1,7 @@ #include "utils/stack.h" ct_stack_t *stack_new() { - ct_stack_t *s = malloc(sizeof(ct_stack_t)); + ct_stack_t *s = mallocz(sizeof(ct_stack_t)); s->count = 0; // 栈顶始终使用空占位符 stack_node *empty = stack_new_node(NULL); @@ -42,7 +42,7 @@ bool stack_empty(ct_stack_t *s) { } stack_node *stack_new_node(void *value) { - stack_node *n = malloc(sizeof(stack_node)); + stack_node *n = mallocz(sizeof(stack_node)); n->next = NULL; n->value = value; return n; diff --git a/utils/table.c b/utils/table.c index a9090605..c347a9cc 100644 --- a/utils/table.c +++ b/utils/table.c @@ -40,6 +40,7 @@ void *table_get(table_t *t, string key) { } bool table_set(table_t *t, char *key, void *value) { + key = strdup(key); // 由于需要内部使用,所以不依赖外部的 key if (t->count + 1 > t->capacity * TABLE_MAX_LOAD) { int capacity = GROW_CAPACITY(t->capacity); table_adjust(t, capacity); @@ -60,11 +61,7 @@ bool table_set(table_t *t, char *key, void *value) { void table_adjust(table_t *t, int capacity) { // 创建一个新的 entries 并初始化 - table_entry *entries = (table_entry *) malloc(sizeof(table_entry) * capacity); - for (int i = 0; i < capacity; ++i) { - entries[i].key = NULL; - entries[i].value = NULL; - } + table_entry *entries = mallocz(sizeof(table_entry) * capacity); t->count = 0; for (int i = 0; i < t->capacity; i++) { @@ -127,7 +124,7 @@ table_entry *table_find_entry(table_entry *entries, int capacity, string key) { } table_t *table_new() { - table_t *t = malloc(sizeof(table_t)); + table_t *t = mallocz(sizeof(table_t)); table_init(t); return t; } diff --git a/utils/table.h b/utils/table.h index 83b5cecb..1b580457 100644 --- a/utils/table.h +++ b/utils/table.h @@ -7,7 +7,7 @@ #define TABLE_MAX_LOAD 0.75 typedef struct { - string key; + char *key; void *value; } table_entry; diff --git a/utils/type.c b/utils/type.c index 3e3503b2..7c3f589d 100644 --- a/utils/type.c +++ b/utils/type.c @@ -34,8 +34,9 @@ static rtype_t rtype_bool() { static rtype_t rtype_nullable_pointer(type_pointer_t *t) { rtype_t value_rtype = reflect_type(t->value_type); - char *str = fixed_sprintf("%d_%lu", TYPE_NULLABLE_POINTER, value_rtype.hash); + char *str = dsprintf("%d_%lu", TYPE_NULLABLE_POINTER, value_rtype.hash); uint32_t hash = hash_string(str); + free(str); rtype_t rtype = { .size = sizeof(n_pointer_t), .hash = hash, @@ -57,8 +58,9 @@ static rtype_t rtype_nullable_pointer(type_pointer_t *t) { static rtype_t rtype_pointer(type_pointer_t *t) { rtype_t value_rtype = reflect_type(t->value_type); - char *str = fixed_sprintf("%d_%lu", TYPE_POINTER, value_rtype.hash); + char *str = dsprintf("%d_%lu", TYPE_POINTER, value_rtype.hash); uint32_t hash = hash_string(str); + free(str); rtype_t rtype = { .size = sizeof(n_pointer_t), .hash = hash, @@ -100,8 +102,9 @@ static rtype_t rtype_string() { static rtype_t rtype_vec(type_vec_t *t) { rtype_t element_rtype = reflect_type(t->element_type); - char *str = fixed_sprintf("%d_%lu", TYPE_VEC, element_rtype.hash); + char *str = dsprintf("%d_%lu", TYPE_VEC, element_rtype.hash); uint32_t hash = hash_string(str); + free(str); rtype_t rtype = { .size = sizeof(n_vec_t), .hash = hash, @@ -124,8 +127,9 @@ rtype_t rtype_array(type_array_t *t) { rtype_t element_rtype = reflect_type(t->element_type); uint64_t element_size = type_sizeof(t->element_type); - char *str = fixed_sprintf("%d_%lu_%lu", TYPE_ARRAY, t->length, element_rtype.hash); + char *str = dsprintf("%d_%lu_%lu", TYPE_ARRAY, t->length, element_rtype.hash); uint32_t hash = hash_string(str); + free(str); rtype_t rtype = { .size = element_size * t->length, .hash = hash, @@ -150,8 +154,9 @@ rtype_t rtype_array(type_array_t *t) { rtype_t rt_rtype_array(rtype_t *element_rtype, uint64_t length) { uint64_t element_size = rtype_out_size(element_rtype, POINTER_SIZE); - char *str = fixed_sprintf("%d_%lu_%lu", TYPE_ARRAY, length, element_rtype->hash); + char *str = dsprintf("%d_%lu_%lu", TYPE_ARRAY, length, element_rtype->hash); uint32_t hash = hash_string(str); + free(str); rtype_t rtype = { .size = element_size * length, .hash = hash, @@ -182,8 +187,9 @@ static rtype_t rtype_map(type_map_t *t) { rtype_t key_rtype = reflect_type(t->key_type); rtype_t value_rtype = reflect_type(t->value_type); - char *str = fixed_sprintf("%d_%lu_%lu", TYPE_MAP, key_rtype.hash, value_rtype.hash); + char *str = dsprintf("%d_%lu_%lu", TYPE_MAP, key_rtype.hash, value_rtype.hash); uint32_t hash = hash_string(str); + free(str); rtype_t rtype = { .size = sizeof(n_map_t), .hash = hash, @@ -206,8 +212,9 @@ static rtype_t rtype_map(type_map_t *t) { static rtype_t rtype_set(type_set_t *t) { rtype_t key_rtype = reflect_type(t->element_type); - char *str = fixed_sprintf("%d_%lu", TYPE_SET, key_rtype.hash); + char *str = dsprintf("%d_%lu", TYPE_SET, key_rtype.hash); uint32_t hash = hash_string(str); + free(str); rtype_t rtype = { .size = sizeof(n_set_t), .hash = hash, @@ -353,7 +360,7 @@ static rtype_t rtype_struct(type_struct_t *t) { // 假设没有 struct, 可以根据所有 property 计算 gc bits uint16_t last_ptr_offset = rtype_struct_gc_bits(gc_bits, &offset, t); - uint64_t *element_hash_list = malloc(sizeof(uint64_t) * t->properties->length); + uint64_t *element_hash_list = mallocz(sizeof(uint64_t) * t->properties->length); // 记录需要 gc 的 key 的 for (int i = 0; i < t->properties->length; ++i) { struct_property_t *p = ct_list_value(t->properties, i); @@ -772,12 +779,15 @@ rtype_t *gc_rtype(type_kind kind, uint32_t count, ...) { va_start(valist, count); for (int i = 0; i < count; i++) { type_kind arg_kind = va_arg(valist, type_kind); - str = str_connect(str, itoa(arg_kind)); + str = str_connect_free(str, itoa(arg_kind)); } va_end(valist); uint64_t hash = hash_string(str); - rtype_t *rtype = table_get(rt_rtype_table, itoa(hash)); + free(str); + str = itoa(hash); + rtype_t *rtype = table_get(rt_rtype_table, str); + free(str); if (rtype) { return rtype; } @@ -809,8 +819,9 @@ rtype_t *gc_rtype(type_kind kind, uint32_t count, ...) { rtype->hash = hash; rtype->in_heap = kind_in_heap(kind); - - table_set(rt_rtype_table, itoa(rtype->hash), rtype); + str = itoa(rtype->hash); + table_set(rt_rtype_table, str, rtype); + free(str); return rtype; } @@ -821,9 +832,12 @@ rtype_t *gc_rtype(type_kind kind, uint32_t count, ...) { */ rtype_t *gc_rtype_array(type_kind kind, uint32_t length) { // 更简单的计算一下 hash 即可 array, len + scan 计算即可 - char *str = fixed_sprintf("%d_%lu_%lu", kind, length, TYPE_POINTER); + char *str = dsprintf("%d_%lu_%lu", kind, length, TYPE_POINTER); uint64_t hash = hash_string(str); - rtype_t *rtype = table_get(rt_rtype_table, itoa(hash)); + free(str); + str = itoa(hash); + rtype_t *rtype = table_get(rt_rtype_table, str); + free(str); if (rtype) { return rtype; } @@ -836,7 +850,9 @@ rtype_t *gc_rtype_array(type_kind kind, uint32_t length) { rtype->gc_bits = malloc_gc_bits(length * POINTER_SIZE); rtype->hash = hash; rtype->in_heap = true; - table_set(rt_rtype_table, itoa(rtype->hash), rtype); + str = itoa(rtype->hash); + table_set(rt_rtype_table, str, rtype); + free(str); return rtype; }