dtl v0.3 Alpha
This commit is contained in:
commit
854b8ac278
119
dtl.h
Normal file
119
dtl.h
Normal file
@ -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 <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
/* 一些基础调试函数 */
|
||||
#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
|
137
log-dtl.c
Normal file
137
log-dtl.c
Normal file
@ -0,0 +1,137 @@
|
||||
#include "dtl.h"
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
|
||||
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];
|
||||
}
|
32
makefile
Normal file
32
makefile
Normal file
@ -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
|
112
mem-dtl.c
Normal file
112
mem-dtl.c
Normal file
@ -0,0 +1,112 @@
|
||||
#include <error.h>
|
||||
#include <string.h>
|
||||
#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;
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user