修复了一个malloc的问题
This commit is contained in:
+55
-26
@@ -8,7 +8,11 @@
|
||||
* 创建日期:2026-09-14
|
||||
* 修改记录:
|
||||
* v1.0 2026-09-14 王建锋 创建初始版本(P3:段键表引擎 + net_cfg 集成)
|
||||
* 函数说明:引擎状态非重入——调用方须收敛同一任务(netTask:poll/save;
|
||||
* v1.1 2026-09-18 王建锋 P0-1:临时缓冲改经 cfg_store_alloc(MCU = FreeRTOS 堆),
|
||||
* 移除对 C 库 malloc 的全部依赖(MicroLIB C 堆仅 512B,
|
||||
* 原 4 处 KB 级 malloc 真机必然失败);增编译期堆峰值预算
|
||||
* 校验 + 失败上报自检记录
|
||||
* 函数说明:引擎状态非重入——调用方须收敛同一任务(defaultTask:poll/save,见 P1-3;
|
||||
* 启动期 load 先于任务竞争);FS 卷并发由 FatFS REENTRANT 卷锁保证
|
||||
* (见《配置文件设计说明》D15 A+ 方案)
|
||||
*/
|
||||
@@ -16,7 +20,7 @@
|
||||
/* 头文件包含区 */
|
||||
#include <string.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdlib.h> /* strtoul(键值解码);堆分配一律走 cfg_store_alloc,禁 malloc */
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
@@ -26,6 +30,8 @@
|
||||
|
||||
#include "cfg_file_store.h"
|
||||
|
||||
#include "sys_log.h" /* 配置读写失败上报自检记录(双端共享接口,MCU 端 preboot/队列安全) */
|
||||
|
||||
#define DBG_TAG "[CFG]"
|
||||
#include "dbg_log.h"
|
||||
|
||||
@@ -41,10 +47,17 @@ static const char s_doc_header[] =
|
||||
"; - 编辑后经 FTP 上传或设备端保存,设备 4s 沉降后自动重载\r\n"
|
||||
"; ============================================================\r\n";
|
||||
|
||||
#define CFG_OUT_MAX 5120u /* 保存输出缓冲(输入复用读缓冲;堆峰值 ≈ 9KB 暂态) */
|
||||
#define CFG_OUT_MAX 5120u /* 保存输出缓冲上限(经 cfg_store_alloc 取,见下方堆峰值预算) */
|
||||
#define CFG_LINE_TEST_MAX 127u /* 受管键行匹配的行长上限(超长必非受管键行) */
|
||||
#define CFG_SNAP_MAX 64u /* 变更检测段快照缓冲(挂回调段 data_size 须 ≤ 此值) */
|
||||
#define CFG_NAME_MAX 16u /* 段名缓冲(15 字符 + NUL) */
|
||||
#define CFG_HEAP_BUDGET 10240u /* 暂态堆峰值预算:读缓冲(1B NUL) + 输出缓冲之和上限 */
|
||||
|
||||
/* 编译期钉死暂态堆峰值:放大 CFG_FILE_MAX_LEN / CFG_OUT_MAX 会先在此编译失败,强制
|
||||
* 改动者重新核对平台堆余量(MCU = FreeRTOS 堆,当前实测余量见《RAM使用分析与优化方案》),
|
||||
* 而不是在真机上退化成运行期分配失败。用 typedef 负数组实现(ARMCC 5 C99 无 C11
|
||||
* _Static_assert);当前峰值 4097 + 5120 = 9217B ≤ 10240B */
|
||||
typedef char cfg_heap_peak_check_t[(CFG_FILE_MAX_LEN + 1u + CFG_OUT_MAX) <= CFG_HEAP_BUDGET ? 1 : -1];
|
||||
|
||||
/* 静态变量定义区 */
|
||||
|
||||
@@ -467,11 +480,11 @@ static int s_gen_document(char *p_buf, size_t cap, size_t *p_len) {
|
||||
}
|
||||
|
||||
/*
|
||||
* 函数功能:读配置文件到堆缓冲(NUL 结尾)
|
||||
* 函数功能:读配置文件到平台堆缓冲(NUL 结尾)
|
||||
* 入口参数:p_pbuf - 缓冲指针输出 uint8_t **
|
||||
* p_len - 实际长度输出 size_t *
|
||||
* 返回值:0 - 成功;-1 - 分配/读失败(缓冲已释放) int
|
||||
* 限定条件:成功时调用方须 free(*p_pbuf)
|
||||
* 限定条件:成功时调用方须 cfg_store_free(*p_pbuf)(MCU = FreeRTOS 堆,勿用 C 库 free)
|
||||
*/
|
||||
static int s_load_file(uint8_t **p_pbuf, size_t *p_len) {
|
||||
uint8_t *p_buf;
|
||||
@@ -482,14 +495,15 @@ static int s_load_file(uint8_t **p_pbuf, size_t *p_len) {
|
||||
return -1;
|
||||
}
|
||||
*p_pbuf = NULL;
|
||||
p_buf = (uint8_t *)malloc(CFG_FILE_MAX_LEN + 1u);
|
||||
p_buf = (uint8_t *)cfg_store_alloc(CFG_FILE_MAX_LEN + 1u);
|
||||
if (p_buf == NULL) {
|
||||
DBG_ERROR("read: malloc %uB FAIL", (unsigned)(CFG_FILE_MAX_LEN + 1u));
|
||||
DBG_ERROR("read: alloc %uB FAIL (heap free %uB)",
|
||||
(unsigned)(CFG_FILE_MAX_LEN + 1u), (unsigned)cfg_store_heap_free());
|
||||
return -1;
|
||||
}
|
||||
r = cfg_store_read(cfg_store_config_path(), p_buf, CFG_FILE_MAX_LEN, &nread);
|
||||
if (r != 0) {
|
||||
free(p_buf);
|
||||
cfg_store_free(p_buf);
|
||||
return -1;
|
||||
}
|
||||
p_buf[nread] = '\0';
|
||||
@@ -519,19 +533,24 @@ static int s_write_doc(const uint8_t *p_buf, size_t len) {
|
||||
* 限定条件:各段 RAM 副本须为期望落盘值
|
||||
*/
|
||||
static int s_write_template(void) {
|
||||
char *p_buf = (char *)malloc(CFG_OUT_MAX);
|
||||
char *p_buf = (char *)cfg_store_alloc(CFG_OUT_MAX);
|
||||
size_t len = 0u;
|
||||
int r;
|
||||
|
||||
if (p_buf == NULL) {
|
||||
DBG_ERROR("template: malloc %uB FAIL", (unsigned)CFG_OUT_MAX);
|
||||
DBG_ERROR("template: alloc %uB FAIL (heap free %uB)",
|
||||
(unsigned)CFG_OUT_MAX, (unsigned)cfg_store_heap_free());
|
||||
syslog_post(SYSLOG_SELFTEST, "cfg heap alloc fail");
|
||||
return -1;
|
||||
}
|
||||
r = s_gen_document(p_buf, CFG_OUT_MAX, &len);
|
||||
if (r == 0) {
|
||||
r = s_write_doc((const uint8_t *)p_buf, len);
|
||||
if (r != 0) {
|
||||
syslog_post(SYSLOG_SELFTEST, "cfg template write fail");
|
||||
}
|
||||
}
|
||||
free(p_buf);
|
||||
cfg_store_free(p_buf);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -979,11 +998,13 @@ int cfg_file_load(void) {
|
||||
|
||||
if (s_load_file(&p_buf, &len) != 0) {
|
||||
DBG_ERROR("load: file read FAIL, factory defaults kept");
|
||||
syslog_post(SYSLOG_SELFTEST, "cfg load read fail");
|
||||
return -1;
|
||||
}
|
||||
s_parse((char *)p_buf, -1);
|
||||
free(p_buf);
|
||||
DBG_INFO("load: OK (%luB)", (unsigned long)st.size);
|
||||
cfg_store_free(p_buf);
|
||||
DBG_INFO("load: OK (%luB, heap free %uB)",
|
||||
(unsigned long)st.size, (unsigned)cfg_store_heap_free());
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
@@ -1030,42 +1051,50 @@ int cfg_file_save(void) {
|
||||
|
||||
if (s_load_file(&p_in, &in_len) != 0) {
|
||||
DBG_ERROR("save: file read FAIL");
|
||||
syslog_post(SYSLOG_SELFTEST, "cfg save read fail");
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Pass 1 在独立副本上切分(避免破坏原文的行结束符);
|
||||
* 副本在 p_out 分配前释放,堆峰值维持 p_in + p_out(约 9KB) */
|
||||
p_in1 = (uint8_t *)malloc(in_len + 1u);
|
||||
* 副本在 p_out 分配前释放,堆峰值维持 p_in + p_out(≤ CFG_HEAP_BUDGET,
|
||||
* 编译期已校验,见文件常量区) */
|
||||
p_in1 = (uint8_t *)cfg_store_alloc(in_len + 1u);
|
||||
if (p_in1 == NULL) {
|
||||
free(p_in);
|
||||
DBG_ERROR("save: malloc %uB FAIL", (unsigned)(in_len + 1u));
|
||||
cfg_store_free(p_in);
|
||||
DBG_ERROR("save: alloc %uB FAIL (heap free %uB)",
|
||||
(unsigned)(in_len + 1u), (unsigned)cfg_store_heap_free());
|
||||
syslog_post(SYSLOG_SELFTEST, "cfg heap alloc fail");
|
||||
return -1;
|
||||
}
|
||||
(void)memcpy(p_in1, p_in, in_len + 1u);
|
||||
|
||||
s_surgical_pass1((char *)p_in1);
|
||||
|
||||
free(p_in1);
|
||||
cfg_store_free(p_in1);
|
||||
|
||||
p_out = (char *)malloc(CFG_OUT_MAX);
|
||||
p_out = (char *)cfg_store_alloc(CFG_OUT_MAX);
|
||||
if (p_out == NULL) {
|
||||
free(p_in);
|
||||
DBG_ERROR("save: malloc %uB FAIL", (unsigned)CFG_OUT_MAX);
|
||||
cfg_store_free(p_in);
|
||||
DBG_ERROR("save: alloc %uB FAIL (heap free %uB)",
|
||||
(unsigned)CFG_OUT_MAX, (unsigned)cfg_store_heap_free());
|
||||
syslog_post(SYSLOG_SELFTEST, "cfg heap alloc fail");
|
||||
return -1;
|
||||
}
|
||||
|
||||
r = s_surgical((char *)p_in, in_len, p_out, CFG_OUT_MAX, &out_len);
|
||||
|
||||
free(p_in);
|
||||
cfg_store_free(p_in);
|
||||
if (r != 0) {
|
||||
free(p_out);
|
||||
cfg_store_free(p_out);
|
||||
DBG_ERROR("save: output overflow, aborted (file untouched)");
|
||||
syslog_post(SYSLOG_SELFTEST, "cfg save overflow");
|
||||
return -1;
|
||||
}
|
||||
r = s_write_doc((const uint8_t *)p_out, out_len);
|
||||
free(p_out);
|
||||
cfg_store_free(p_out);
|
||||
if (r != 0) {
|
||||
DBG_ERROR("save: file write FAIL");
|
||||
syslog_post(SYSLOG_SELFTEST, "cfg save write fail");
|
||||
return -1;
|
||||
}
|
||||
DBG_INFO("save: OK (surgical, %uB -> %uB)", (unsigned)in_len, (unsigned)out_len);
|
||||
@@ -1120,7 +1149,7 @@ void cfg_file_poll(void) {
|
||||
}
|
||||
|
||||
if (len > CFG_FILE_MAX_LEN) {
|
||||
free(p_buf);
|
||||
cfg_store_free(p_buf);
|
||||
for (i = 0; i < (int)CFG_FILE_MAX_SECTIONS; i++) {
|
||||
if (s_sections[i].used != 0) {
|
||||
(void)memcpy(s_sections[i].p_data, s_sections[i].p_defaults,
|
||||
@@ -1152,7 +1181,7 @@ void cfg_file_poll(void) {
|
||||
s_parse((char *)p_buf, i);
|
||||
}
|
||||
}
|
||||
free(p_buf);
|
||||
cfg_store_free(p_buf);
|
||||
DBG_INFO("poll: config file reloaded");
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user