From 854b8ac2780321b96c087cb9428ae6f4d4479272 Mon Sep 17 00:00:00 2001 From: rangersly <2281598291@qq.com> Date: Sun, 1 Jun 2025 21:17:47 +0800 Subject: [PATCH] dtl v0.3 Alpha --- dtl.h | 119 +++++++++++++++++++++++++++++++++++++++++++++++ log-dtl.c | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ makefile | 32 +++++++++++++ mem-dtl.c | 112 ++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 400 insertions(+) create mode 100644 dtl.h create mode 100644 log-dtl.c create mode 100644 makefile create mode 100644 mem-dtl.c diff --git a/dtl.h b/dtl.h new file mode 100644 index 0000000..018d446 --- /dev/null +++ b/dtl.h @@ -0,0 +1,119 @@ +/* +Copyright(c) 2025 Rangersly All rights reserved. + +DEBUG TOOLS + +Version: v0.1-Alpha 添加了字符串检查输出调试报错 + v0.1-Beta + v0.2-Alpha 添加了内存函数重封装 + v0.3-Alpha 添加了日志系统 +*/ + +#ifndef DEBUGTOOLS +#define DEBUGTOOLS + +#include +#include +#include + + +/* 一些基础调试函数 */ +#ifdef DEBUG + /* 字符串检查宏,输出字符串的每一位数据 */ + #define print_str(str, len) do{ \ + size_t _len = (size_t)len; \ + printf("%s\n", str); \ + for(int i = 0; i < _len; i++) \ + printf("%2x -- %c\n", i, (char)str[i], (uint8_t)str[i]); \ + }while(0) + + /* 输出调试错误报错信息,辅助定位错误地点 */ + #define PERROR(str) printf("%s:%d:%s:\n%s\n", __FILE__, __LINE__, __func__, str); exit(0) +#else + #define print_str(str, len) + #define PERROR(str) +#endif +/*----------------------------------------------*/ + + + +/* 内存函数重封装 */ +#ifdef DEBUG + /* 显示当前的内存情况 */ + #define display_memory_status() __display_memory_status() + /* 重封装malloc函数,第二个参数是内存块说明 */ + #define _malloc(size, message) __malloc(size, message) + /* 重封装free */ + #define _free(point) __free(point) +#else + /* 非调试版本 */ + #define display_memory_status() + #define _malloc(size, message) malloc(size) + #define _free(point) free(point) +#endif + +struct Memory_info { + size_t size; /* 内存块大小 */ + struct Memory_info *next; /* 下一个内存块 */ + void *address; /* 内存块地址 */ + char message[32]; /* 内存块信息 */ +}; +struct Memory_status { + size_t all_size; /* 使用的内存总大小 */ + int count; /* 当前内存块个数 */ + struct Memory_info *front; /* 存储信息头部 */ +}; + +void* +__malloc(size_t size, const char *a); + +void +__free(void *ptr); + +void +__display_memory_status(void); +/*----------------------------------------------*/ + + + +/* 日志系统 */ +enum LOG_LEVEL{ + LOG_INFO = 0, + LOG_WARNING = 1, + LOG_ERROR = 2, + LOG_FATAL = 3 +}; + +/* 最大日志头长度 */ +#define LOG_HEAD_MAX_FORMAT 32 + +/* 设置日志输出 */ +void +log_setoutfile(const char *restrict filename); + +/* 设置日志的最低输出等级 */ +void +log_setlevel(enum LOG_LEVEL level); + +/* 设置日志头,最大不可超过15个字符 */ +void +log_sethead(const char *restrict head); +/* + * 符号表 + * %Y year + * %M month + * %d day + * %h hour + * %m minute + * %s second + * %n number + * %c core time .3f + */ + +/* 输出日志,包含日志等级与日志信息 */ +void +log_print(enum LOG_LEVEL level, const char *restrict message); + +/*----------------------------------------------*/ + +#endif diff --git a/log-dtl.c b/log-dtl.c new file mode 100644 index 0000000..668e0bd --- /dev/null +++ b/log-dtl.c @@ -0,0 +1,137 @@ +#include "dtl.h" +#include +#include + +static enum LOG_LEVEL low_show_level = LOG_INFO; +static uint32_t log_number = 1; +static FILE *log_out_fp = NULL; +static char log_head_format[LOG_HEAD_MAX_FORMAT] = "[%y-%m-%d-%n]"; +static char log_head[LOG_HEAD_MAX_FORMAT << 3]; + + +/* + * 解析日志头 + * + * Description: + * 解析log_head_format中的特殊符号 + * ret 0 -> success + * ret !0 -> Unrecognized symbol + */ +static void +get_loghead(void); + +static void +int_to_str(char *restrict dst, uint32_t num, size_t n); + + +/*-----------------------------------------------------------*/ +/*-----------------------------------------------------------*/ + + +void +log_setoutfile(const char *restrict filename) +{ + if((log_out_fp = fopen(filename, "w")) == NULL) + perror("log-dtl.c:log_setoutfile: Failed to open file !\n"); +} + + +void +log_setlevel(enum LOG_LEVEL level) { + if(level < LOG_INFO || level > LOG_FATAL) + low_show_level = LOG_INFO; + else + low_show_level = level; +} + + +void +log_sethead(const char *restrict head) { + if(strlen(head) >= LOG_HEAD_MAX_FORMAT) + return; + strncpy(log_head_format, head, LOG_HEAD_MAX_FORMAT); +} + + +void +log_print(enum LOG_LEVEL level, const char *restrict message) { + if(log_out_fp == NULL) + log_out_fp = stdout; + if(level < low_show_level) + return; + + get_loghead(); + fputs(log_head, log_out_fp); + + switch(level) { // 打印错误等级 + case LOG_INFO: + fputs("INFO:", log_out_fp);break; + case LOG_WARNING: + fputs("WARNING:", log_out_fp);break; + case LOG_ERROR: + fputs("ERROR:", log_out_fp);break; + case LOG_FATAL: + fputs("FATAL:", log_out_fp);break; + } + + fputs(message, log_out_fp); + fputc('\n', log_out_fp); + log_number++; // 日志计数++ +} + + +void +get_loghead(void) { + char buf[32]; + time_t now_time = time(NULL); + clock_t core_time = clock() / CLOCKS_PER_SEC; + struct tm *tm_time = localtime(&now_time); + + memset(log_head, '\0', sizeof(log_head)); + + for(int i = 0; i < strlen(log_head_format); i++) { + if(log_head_format[i] != '%') { + log_head[strlen(log_head)] = log_head_format[i]; + continue; + } + i++; + switch(log_head_format[i]) { // 特殊字符转换 + case 'Y': + strftime(buf, 32, "%Y", tm_time);break; + case 'M': + strftime(buf, 32, "%m", tm_time);break; + case 'd': + strftime(buf, 32, "%d", tm_time);break; + case 'h': + strftime(buf, 32, "%H", tm_time);break; + case 'm': + strftime(buf, 32, "%M", tm_time);break; + case 's': + strftime(buf, 32, "%S", tm_time);break; + case 'n': + int_to_str(buf, log_number, 32);break; + case 'c': + int_to_str(buf, core_time, 32);break; + default: + strcpy(buf, "!!"); + } + strcat(log_head, buf); + } +} + +void +int_to_str(char *restrict dst, uint32_t num, size_t n) { + // 逐位提取数字(反向存储) + int start = 0; + do { + dst[start++] = num % 10 + '0'; + num /= 10; + } while (num > 0); + dst[start] = '\0'; + + // 反转数字部分 + char buf[16]; + strncpy(buf, dst, 15); + for(int i = 0; i < strlen(buf); i++) + dst[--start] = buf[i]; +} diff --git a/makefile b/makefile new file mode 100644 index 0000000..ef57455 --- /dev/null +++ b/makefile @@ -0,0 +1,32 @@ +# 编译器与工具配置 +CC := gcc +AR := ar +CFLAGS := -Wall -O2 -fPIC -MMD # 启用优化、位置无关代码和依赖生成 +ARFLAGS := rcs # 静态库打包选项 + +# 文件与目标 +SRC := $(wildcard *.c) # 所有源文件 +OBJS := $(patsubst %.c,%.o,$(SRC)) # 目标文件 +DEPS := $(OBJS:.o=.d) # 依赖文件 +TARGET := libdtl.a # 最终库文件 + +# 默认目标 +all: $(TARGET) + +# 生成静态库 +$(TARGET): $(OBJS) + $(AR) $(ARFLAGS) $@ $^ + +# 编译目标文件(支持多线程) +%.o: %.c + $(CC) $(CFLAGS) -c $< -o $@ + +# 包含自动生成的依赖文件 +-include $(DEPS) + +# 清理 +clean: + rm -f $(OBJS) $(DEPS) $(TARGET) + +# 声明伪目标 +.PHONY: all clean diff --git a/mem-dtl.c b/mem-dtl.c new file mode 100644 index 0000000..32c9cd0 --- /dev/null +++ b/mem-dtl.c @@ -0,0 +1,112 @@ +#include +#include +#include "dtl.h" + +/* Memory_info 结构 伪构造函数 */ +static struct Memory_info * +memory_info_init(size_t size, struct Memory_info *next, const char *a); + +/* Memory_status 结构初始化函数 */ +static void +memory_status_init(void); + +static struct Memory_status memory_status_dbtools = {0, 0, NULL}; + +void +memory_status_init(void) +{ + memory_status_dbtools.all_size = 0; + memory_status_dbtools.count = 0; + memory_status_dbtools.front = memory_info_init(0, NULL, "root"); +} + +void* +__malloc(size_t size, const char *a) +{ + /* 确保已经初始化 */ + if(memory_status_dbtools.front == NULL) + memory_status_init(); + + struct Memory_info *it = memory_status_dbtools.front; + /* 寻找不大于当前内存块的第一个位置 */ + while((it->next != NULL) && (it->next->size > size)) + it = it->next; + + /* 分配内存块 */ + it->next = memory_info_init(size, it->next, a); + + /* 分配成功 修改总数据 */ + memory_status_dbtools.all_size += size; + memory_status_dbtools.count++; + + return it->next->address; +} + + +void +__free(void *ptr) +{ + /* 避免释放不存在的内存 */ + if(NULL == ptr) + return; + + /* 确保已经初始化 */ + if(memory_status_dbtools.front == NULL) + memory_status_init(); + + struct Memory_info *it = memory_status_dbtools.front; + while(it->next != NULL) { + /* 找到对应的地址块信息就在信息链表中删除 */ + if(ptr == it->next->address) { + struct Memory_info *temp = it->next->next; + memory_status_dbtools.all_size -= it->next->size; + memory_status_dbtools.count--; + + free(ptr); + ptr = NULL; + free(it->next); + it->next = temp; + break; + } + it = it->next; + } +} + +extern void +__display_memory_status(void) +{ + printf("\n---Memory status---\n"); + printf("All_size: %ld\n", memory_status_dbtools.all_size); + printf("count: %d\n", memory_status_dbtools.count); + + printf("--- Stat Info ---\n"); + struct Memory_info *it = memory_status_dbtools.front->next; + while(NULL != it) { + printf("%p\n", it->address); + printf("%ld\n", it->size); + printf(it->message); + printf("\n----------------\n"); + it = it->next; + } + printf("\n\n"); +} + + +struct Memory_info * +memory_info_init(size_t size, struct Memory_info *next, const char *a) +{ + struct Memory_info *dst; + dst = (struct Memory_info*)malloc(sizeof(struct Memory_info)); + if(NULL == dst) + perror("memory_info_init: malloc fail!"); + + dst->size = size; + dst->next = next; + if(size != 0) { + dst->address = malloc(size); + if(NULL == dst->address) + perror("memory_info_init: malloc fail!"); + } else dst->address = NULL; + strncpy(dst->message, a, 31); + return dst; +}