添加错误映射文件的处理防止崩溃,优化mq处理topic前缀,添加空指针预防

This commit is contained in:
lnk
2026-06-02 16:23:23 +08:00
parent c388bd04fe
commit 465e304085
7 changed files with 367 additions and 73 deletions

View File

@@ -1527,8 +1527,8 @@ int parse_rpt_log_ini()
}
for (cpuno = 0; cpuno < ied->cpucount; cpuno++) {
LD_info = &(ied_usr->LD_info[cpuno]);
for (cpuno = 0; cpuno < ied->cpucount; cpuno++) {//遍历所有测点但是某些测点可能为空台账初始化时ied->cpucount取的是测点号
LD_info = &(ied_usr->LD_info[cpuno]);//测点号从1开始cpuno从0开始所以ied_usr->LD_info[cpuno]对应测点号为cpuno+1注意台账初始化时ied_usr->LD_info数组的大小是按照测点总数分配的所以有些测点号可能没有对应的LD_info添加判断防止崩溃
//char str[256]; //256大小
char* tmp = Get_IED(ied_usr->dev_type);
if(tmp == NULL){std::cerr << "front read ied config error!" << std::endl;continue;}
@@ -1542,10 +1542,21 @@ int parse_rpt_log_ini()
//调试用
printf("%s使用内存地址 LD_name[%d]: %p\n", ied_usr->terminal_id, cpuno, (void*)ied_usr->LD_info[cpuno].LD_name);
//添加判断有的监测点没有cpuno为2直接申请了LD_info[1]没申请LD_info[0]
if(ied_usr->LD_info[cpuno].LD_name == NULL){
//添加判断,比如有的监测点没有cpuno为2直接申请了LD_info[1]没申请LD_info[0]
if(ied_usr->LD_info[cpuno].LD_name == NULL){ //空说明台账初始化没申请空间
printf("this ld_info didn't palloc space ,maybe this ledger has problem!");
DIY_ERRORLOG_CODE("process",0,LOG_CODE_RPTINIT,"【ERROR】终端%s的监测点序号为%d的监测点无法初始化报告,这个装置的台账存在缺失,请检查装置台账的监测点总数和各监测点的序号",ied_usr->terminal_id,cpuno + 1);
//添加默认值防止崩溃20260601
LD_info->rptcount = 0;
LD_info->logcount = 0;
LD_info->cpuno = 0;
LD_info->LD_name = NULL;
LD_info->rptinfo = NULL;
LD_info->loginfo = NULL;
delete[] tmp;//释放内存
continue;//跳过防止崩溃
}
@@ -1559,7 +1570,19 @@ int parse_rpt_log_ini()
apr_snprintf(buf, sizeof(buf), "%s", rpt_cfg_strlists[type]->at(i).toAscii().constData());
fill_rptctrl_by_cfg(LD_info, i, buf);
//fill_rptctrl_by_cfg(LD_info, i, buf);
int ret = fill_rptctrl_by_cfg(LD_info, i, buf);
if (ret != 0) {
printf("[RPT_INIT][ERROR] fill_rptctrl_by_cfg failed dev=%s cpu=%d rpt=%d cfg=%s\n",
ied_usr->terminal_id, cpuno, i, buf);
DIY_ERRORLOG_CODE(ied_usr->terminal_id,1,LOG_CODE_RPTINIT,"【ERROR】终端%s的监测点序号为%d的监测点的第%d个报告配置解析失败请检查报告配置格式是否正确",ied_usr->terminal_id, cpuno + 1, i + 1);
if (LD_info->rptinfo && LD_info->rptinfo[i]) {
LD_info->rptinfo[i]->rptID = NULL;
LD_info->rptinfo[i]->LD_info = NULL;
}
}
}
@@ -3011,6 +3034,10 @@ void Cout_account_information() {
add_comm_log(const_cast<char*>(text.toLocal8Bit().constData()));
for (cpuno = 0; cpuno < ied->cpucount; cpuno++) {
LD_info = &(ied_usr->LD_info[cpuno]);
if (LD_info->cpuno == 0 || LD_info->LD_name == NULL)
continue;
QString text2;//待组装的pgsql语句
text2.append(QString("mp_id: \"%1\" terminal_code:\"%2\" ").arg(LD_info->mp_id).arg(LD_info->terminal_code));
add_comm_log(const_cast<char*>(text2.toLocal8Bit().constData()));
@@ -4526,7 +4553,7 @@ int parse_device_cfg_web()
//otl_datetime timestamp;
int monitor_log_level = 1;//监测点日志等级
//for (int j = 0; j < 10; ++j) { // 假设最多有10个监测点
for (int j = 0; value->line[j].monitor_id[0] != '\0'; ++j){
for (int j = 0; value->line[j].monitor_id[0] != '\0'; ++j){//只看有测点号的监测点,避免访问无效数据
ledger_monitor& monitor = value->line[j];
// 检查监测点 ID 是否为空以避免访问无效数据
/*if (monitor.monitor_id[0] != '\0') {
@@ -4548,27 +4575,33 @@ int parse_device_cfg_web()
strncpy(monitor_status, monitor.status, sizeof(monitor_status) - 1);//添加监测点状态
monitor_log_level = monitor.log_level;//监测点日志等级
//监测点台账处理
count_real_monitor++;
memset(&line_info, 0, sizeof(line_info));
line_info.line_id = count_real_monitor; //监测点排号
count_real_monitor++;//初始为0进入一次+1有效监测点排号从1开始
memset(&line_info, 0, sizeof(line_info));//有效测点的初始化
line_info.line_id = count_real_monitor; //监测点排号,前置本地使用
cout << "line_id:" << line_info.line_id << endl;
strcpy(line_info.mp_id, monitor_id);
strcpy(line_info.mp_id, monitor_id);//测点id
cout << "mp_id:" << line_info.mp_id << endl;
strcpy(line_info.terminal_code, terminal_code); //从上级获取的终端号
cout << "terminal_code:" << line_info.terminal_code << endl;
if (isCharPtrEmpty(logical_device_seq)) {
line_info.cpuno = 1; //默认监测点实例号1
cout << "logical_device_seq:is null,set cpuno:"<< line_info.cpuno << endl;
}
else {
line_info.cpuno = std::atoi(logical_device_seq);
line_info.cpuno = std::atoi(logical_device_seq); //台账实例号,即台账的测点号
cout << "logical_device_seq:"<< line_info.cpuno << endl;
}
//cout << "cpuno:" << line_info.cpuno << endl;
strcpy(line_info.voltage_level, voltage_level);
strcpy(line_info.voltage_level, voltage_level);//电压等级
cout << "voltage_level:" << line_info.voltage_level << endl;
strcpy(line_info.v_wiring_type, terminal_connect);
strcpy(line_info.v_wiring_type, terminal_connect);//接线方式
cout << "v_wiring_type:" << line_info.v_wiring_type << endl;
//lnk2024-8-14记录接线标志
if (strcmp(line_info.v_wiring_type, "0") != 0)
{
@@ -4576,7 +4609,7 @@ int parse_device_cfg_web()
cout << "monitor_id" << monitor_id << "v_wiring_type:" << line_info.v_wiring_type << "is delta wiring:" << isdelta_flag << endl;
DIY_WARNLOG_CODE("process",0,LOG_CODE_LEDGER,"【WARN】前置连接的监测点 %s 是角形接线,对应终端为%s 终端类型是%s",line_info.mp_id,ied_usr->terminal_id,ied_usr->dev_type);
}
strcpy(line_info.monitor_status, monitor_status);
strcpy(line_info.monitor_status, monitor_status);//测点状态
cout << "monitor_status:" << line_info.monitor_status << endl;
//// 构造struct tm对象
struct tm timeinfo;
@@ -4587,27 +4620,32 @@ int parse_device_cfg_web()
timeinfo.tm_min = timestamp.minute;
timeinfo.tm_sec = timestamp.second;
time_t time = std::mktime(&timeinfo);
line_info.time = static_cast<long long>(time);
line_info.time = static_cast<long long>(time);//测点更新时间
cout << "time:" << line_info.time << endl;
strcpy(line_info.name, monitor_name);
strcpy(line_info.name, monitor_name);//测点名
cout << "name:" << line_info.name << endl;
line_info.read_flag = ENABLE; //监测点有效
line_info.log_level = monitor_log_level; //监测点日志等级
cout << "log_level_monitor:" << line_info.log_level << endl;
//ied = find_ied_from_dev_code(line_info.terminal_code); //不需要再找上级终端了,已经在终端里了
if (ied && ied->usr_ext && line_info.cpuno && (static_cast<int>(line_info.cpuno) < 10)) {
if (ied && ied->usr_ext && line_info.cpuno && (static_cast<int>(line_info.cpuno) < 10)) {//台账测点号有效
char str[256]; //256大小
byte_t cpuno = line_info.cpuno;
byte_t cpuno = line_info.cpuno; //台账的测点号
cout << "cpuno:" << (int)line_info.cpuno << endl;
cout << "index cpuno:" << cpuno-1 << endl;
ied_usr = (ied_usr_t*)ied->usr_ext;
ied_usr->LD_info[cpuno - 1] = line_info; //cpuno默认是1
ied_usr->LD_info[cpuno - 1].ied = ied;
ied_usr->LD_info[cpuno - 1].ied = ied; //父级指针绑定
apr_snprintf(str, sizeof(str), "PQMonitorPQM%d", cpuno);//将监测点逻辑号转为PQMonitorPQM+逻辑号
//lnk20250208不使用apr_pstrdup后续直接复用
//ied_usr->LD_info[cpuno - 1].LD_name = apr_pstrdup(g_init_pool, str);//将 str 中的格式化字符串复制到内存池 g_init_pool 中。ied_usr->LD_info[cpuno - 1].LD_name 存储了这个字符串的副本LD_name 现在是 PQMonitorPQM{cpuno} 的形式。
// 从 g_init_pool 内存池中分配固定 256 字节的内存
ied_usr->LD_info[cpuno - 1].LD_name = (char *)apr_palloc(g_init_pool, 256);
ied_usr->LD_info[cpuno - 1].LD_name = (char *)apr_palloc(g_init_pool, 256);//根据台账中的测点号申请内存
//调试用,申请的地址
printf("%s分配内存地址 LD_name[%d]: %p\n", ied_usr->terminal_id, cpuno - 1, (void*)ied_usr->LD_info[cpuno - 1].LD_name);
// 清空内存,防止残留数据
@@ -4618,21 +4656,21 @@ int parse_device_cfg_web()
//这里申请的空间基于ied的数量挂载到ied上
ied_usr->LD_info[cpuno - 1].ht_fcd = apr_hash_make(g_init_pool); //这两行代码分别为 ied_usr->LD_info[cpuno - 1] 的两个成员ht_fcd 和 ht_full_fcda创建了空的哈希表。apr_hash_make(g_init_pool) 会在 g_init_pool 内存池中为这两个哈希表分配内存空间
ied_usr->LD_info[cpuno - 1].ht_full_fcda = apr_hash_make(g_init_pool);//它们的 key 值和 value 在后续的代码中可能会被填充
ied_usr->LD_info[cpuno - 1].rptcount = 0;
ied_usr->LD_info[cpuno - 1].rptcount = 0;//有效测点报告数为初始为0
cout << "rptcount:" << ied_usr->LD_info[cpuno - 1].rptcount << endl;
if (cpuno > ied->cpucount) {
ied->cpucount = cpuno;
if (cpuno > ied->cpucount) {//测点号大于测点数
ied->cpucount = cpuno;//取测点号,后续遍历测点时需要跳过无效测点
}
}
}
}
//////////////////////////////////////////////////////////////////////////////////////////////////
if (count_real < count_cfg){
if (count_real < count_cfg){//读取计数器和台账数量对比,如果读取的数量小于台账数量,说明有些台账读取失败了,按照读取的数量来设置进程的台账数量,避免后续访问读取失败的台账导致崩溃
g_node->n_clients = count_real;
}
if (count_cfg != count_real){
if (count_cfg != count_real){//应该相等,如果不相等说明有些台账读取失败了,按照读取的数量来设置进程的台账数量,避免后续访问读取失败的台账导致崩溃
return APR_EBADF;
}
@@ -6169,10 +6207,22 @@ int parse_rpt_log_ini_one(ied_t* ied)
//调试
printf("%s使用内存地址 LD_name[%d]: %p\n", ied_usr->terminal_id, cpuno, (void*)ied_usr->LD_info[cpuno].LD_name);
//添加判断有的监测点没有cpuno为2直接申请了LD_info[2-1]没申请LD_info[0]
if(ied_usr->LD_info[cpuno].LD_name == NULL){
printf("this ld_info didn't palloc space ,maybe this ledger has problem!");
DIY_ERRORLOG_CODE("process",0,LOG_CODE_RPTINIT,"【ERROR】终端%s的监测点序号为%d的监测点无法初始化报告,这个装置的台账存在缺失,请检查装置台账的监测点总数和各监测点的序号",ied_usr->terminal_id,cpuno + 1);
//添加默认值防止崩溃20260601
LD_info->rptcount = 0;
LD_info->logcount = 0;
LD_info->cpuno = 0;
LD_info->LD_name = NULL;
LD_info->rptinfo = NULL;
LD_info->loginfo = NULL;
delete[] tmp;//Get_IED中分配了内存使用后删除
continue;//跳过防止崩溃
}
@@ -6191,7 +6241,18 @@ int parse_rpt_log_ini_one(ied_t* ied)
init_rptctrl_by_count(LD_info, rpt_cfg_strlists[type]->size());
for (int i = 0; i < rpt_cfg_strlists[type]->size(); ++i) {
apr_snprintf(buf, sizeof(buf), "%s", rpt_cfg_strlists[type]->at(i).toAscii().constData());
fill_rptctrl_by_cfg(LD_info, i, buf);
//fill_rptctrl_by_cfg(LD_info, i, buf);
int ret = fill_rptctrl_by_cfg(LD_info, i, buf);
if (ret != 0) {
printf("[RPT_INIT][ERROR] fill_rptctrl_by_cfg failed dev=%s cpu=%d rpt=%d cfg=%s\n",
ied_usr->terminal_id, cpuno, i, buf);
DIY_ERRORLOG_CODE(ied_usr->terminal_id,1,LOG_CODE_RPTINIT,"【ERROR】终端%s的监测点序号为%d的监测点的第%d个报告配置解析失败请检查报告配置格式是否正确",ied_usr->terminal_id, cpuno + 1, i + 1);
if (LD_info->rptinfo && LD_info->rptinfo[i]) {
LD_info->rptinfo[i]->rptID = NULL;
LD_info->rptinfo[i]->LD_info = NULL;
}
}
}
//初始化监测点的日志控制
init_logctrl_by_count(LD_info, log_cfg_strlists[type]->size());