修复VrUtils单一初始化

This commit is contained in:
yiyi 2026-01-04 23:11:31 +08:00
parent 4d9f7170ee
commit 3756a63a32
5 changed files with 92 additions and 44 deletions

View File

@ -148,7 +148,7 @@ win32:CONFIG(release, debug|release): {
}
else:win32:CONFIG(debug, debug|release): {
LIBS += -L$$PWD/../../../AppAlgo/particleSizeMeasure/Windows/x64/Debug -lparticleSizeMeasurement -lbaseAlgorithm
LIBS += -L$$PWD/../../../SDK/OpenCV320/Windows/vc14/Debug -lopencv_world320d
LIBS += -L$$PWD/../../../SDK/OpenCV320/Windows/vc14/Release -lopencv_world320
}
else:unix:!macx: {
LIBS += -L$$PWD/../../../AppAlgo/particleSizeMeasure/Arm/aarch64 -lparticleSizeMeasurement -lbaseAlgorithm

View File

@ -11,6 +11,7 @@
#include <QThread>
#include <QApplication>
#include <QCoreApplication>
#include <QDateTime>
#include <cmath>
@ -24,6 +25,16 @@ WheelMeasurePresenter::WheelMeasurePresenter(QObject* parent)
WheelMeasurePresenter::~WheelMeasurePresenter()
{
// 清除状态回调,防止后续回调访问已销毁对象
m_statusUpdate = nullptr;
// 停止顺序检测
m_stopSequentialRequested = true;
m_sequentialDetecting = false;
// 处理待处理的 Qt 事件,确保 QueuedConnection 的回调不会访问已销毁对象
QCoreApplication::processEvents();
if (m_config) {
delete m_config;
m_config = nullptr;

View File

@ -41,9 +41,6 @@ win32:CONFIG(debug, debug|release) {
LIBS += -L../../../AppUtils/AppCommon/debug -lAppCommon
LIBS += -L../../../Module/ModbusTCPServer/debug -lModbusTCPServer
LIBS += -L../../../VrNets/debug -lVrModbus
# VzNLSDK
LIBS += -L../../../SDK/Device/VzNLSDK/Windows/x64/Debug -lVzKerneld
} else:win32:CONFIG(release, debug|release) {
LIBS += -L../WheelMeasureConfig/release -lWheelMeasureConfig
LIBS += -L../../../VrNets/release -lVrTcpClient
@ -54,9 +51,6 @@ win32:CONFIG(debug, debug|release) {
LIBS += -L../../../AppUtils/AppCommon/release -lAppCommon
LIBS += -L../../../Module/ModbusTCPServer/release -lModbusTCPServer
LIBS += -L../../../VrNets/release -lVrModbus
# VzNLSDK
LIBS += -L../../../Device/VrEyeDevice/release -lVrEyeDevice
}else:unix:!macx {
# 注意:静态库链接顺序很重要,被依赖的库必须放在后面
LIBS += -L../WheelMeasureConfig -lWheelMeasureConfig

View File

@ -4,6 +4,7 @@
#include <fstream>
#include <QFileInfo>
#include <QString>
#include <QCoreApplication>
#include "PathManager.h"
#include "IYModbusTCPServer.h"
@ -22,11 +23,17 @@ BasePresenter::BasePresenter(QObject *parent)
BasePresenter::~BasePresenter()
{
// 清除状态回调指针,防止后续回调访问
m_pStatusCallback = nullptr;
// 等待初始化线程完成
if (m_initThread.joinable()) {
m_initThread.join();
}
// 处理待处理的 Qt 事件,确保 QueuedConnection 的回调执行时检查到 m_pStatusCallback 为空
QCoreApplication::processEvents();
// 停止检测线程
StopAlgoDetectThread();

View File

@ -4,6 +4,8 @@
#include <cstring>
#include <stdarg.h>
#include <clocale>
#include <mutex>
#include <atomic>
#include <log4cpp/Category.hh>
#include <log4cpp/Appender.hh>
@ -41,10 +43,29 @@
#define LOG_CONFIG_FILE "config.ini"
#define LOG_PRINT_FILE "AppLog.log"
static log4cpp::PatternLayout* m_pLayout = nullptr;
static log4cpp::RollingFileAppender* m_prollfileAppender = nullptr;
static bool g_isLogInitialized = false;
static bool g_isTimeEnabled = true;
// 使用函数内静态变量实现真正的全局单例(跨静态库安全)
struct VrLogState {
log4cpp::PatternLayout* pLayout = nullptr;
log4cpp::RollingFileAppender* pRollFileAppender = nullptr;
std::atomic<bool> isInitialized{false};
std::atomic<bool> isShutdown{false}; // 标记日志系统是否已关闭(程序退出时)
std::atomic<bool> isTimeEnabled{true};
std::once_flag initFlag;
std::once_flag uninitFlag;
};
// 函数内静态变量,确保跨编译单元的唯一性
static VrLogState& GetLogState() {
static VrLogState state;
return state;
}
// 兼容旧代码的访问方式
#define m_pLayout (GetLogState().pLayout)
#define m_prollfileAppender (GetLogState().pRollFileAppender)
#define g_isLogInitialized (GetLogState().isInitialized)
#define g_isLogShutdown (GetLogState().isShutdown)
#define g_isTimeEnabled (GetLogState().isTimeEnabled)
#ifdef STM32_UCOSIII
@ -165,14 +186,9 @@ public:
// 静态实例,程序启动时自动初始化日志,程序退出时自动清理日志
static VrLogAutoCleaner g_logAutoCleaner;
/// 初始化log
void VrLogUtils::InitLog()
// 实际执行初始化的内部函数
static void DoInitLog()
{
// 防止重复初始化
if (g_isLogInitialized) {
return;
}
#ifdef _WIN32
// 设置控制台代码页为 UTF-8解决中文乱码
SetConsoleOutputCP(CP_UTF8);
@ -204,25 +220,26 @@ void VrLogUtils::InitLog()
}
// create file appender
if (nullptr == m_pLayout)
VrLogState& state = GetLogState();
if (nullptr == state.pLayout)
{
m_pLayout = new log4cpp::PatternLayout;
state.pLayout = new log4cpp::PatternLayout;
// 设置布局格式,可以控制是否自动换行
// %d{%Y-%m-%d %H:%M:%S.%l} [%p] %c - %m%n
// 其中 %n 表示换行符,如果想要控制换行可以去掉或修改这个
m_pLayout->setConversionPattern("%d{%Y-%m-%d %H:%M:%S.%l} [%p] %m");
state.pLayout->setConversionPattern("%d{%Y-%m-%d %H:%M:%S.%l} [%p] %m");
}
if (nullptr == m_prollfileAppender)
if (nullptr == state.pRollFileAppender)
{
m_prollfileAppender = new log4cpp::RollingFileAppender("AppLogAppender", logPath + PATH_SEP + LOG_PRINT_FILE,
state.pRollFileAppender = new log4cpp::RollingFileAppender("AppLogAppender", logPath + PATH_SEP + LOG_PRINT_FILE,
1024 * 1024, // 单个文件大小1M
10); // 10个文件
m_prollfileAppender->setLayout(m_pLayout);
state.pRollFileAppender->setLayout(state.pLayout);
// add appender to category
log4cpp::Category& root = log4cpp::Category::getRoot();
root.addAppender(m_prollfileAppender);
root.addAppender(state.pRollFileAppender);
// set priority
root.setPriority(log4cpp::Priority::DEBUG);
@ -232,27 +249,41 @@ void VrLogUtils::InitLog()
g_isLogInitialized = true;
}
/// 关闭log
void VrLogUtils::UninitLog()
/// 初始化log
void VrLogUtils::InitLog()
{
if (!g_isLogInitialized) {
// 如果已经关闭,不再初始化
if (g_isLogShutdown) {
return;
}
if (m_pLayout)
{
delete m_pLayout;
m_pLayout = nullptr;
// 使用 call_once 确保只执行一次初始化(跨静态库安全)
std::call_once(GetLogState().initFlag, DoInitLog);
}
if (m_prollfileAppender)
// 实际执行清理的内部函数
static void DoUninitLog()
{
delete m_prollfileAppender;
m_prollfileAppender = nullptr;
}
log4cpp::Category::shutdown();//关闭Category;
// 先设置标志,防止其他线程继续调用日志
g_isLogInitialized = false;
g_isLogShutdown = true; // 标记已关闭,防止 EchoLog 重新初始化
// 注意:不调用 log4cpp::Category::shutdown()
// 原因静态对象析构顺序不确定log4cpp 内部的静态对象可能在
// VrLogAutoCleaner 之前就已经被析构,此时调用 shutdown() 会崩溃。
// 程序退出时,操作系统会自动回收所有内存,不需要手动清理。
// 只置空指针,不删除对象(对象由 log4cpp 内部管理)
VrLogState& state = GetLogState();
state.pLayout = nullptr;
state.pRollFileAppender = nullptr;
}
/// 关闭log
void VrLogUtils::UninitLog()
{
// 使用 call_once 确保只执行一次清理(跨静态库安全)
std::call_once(GetLogState().uninitFlag, DoUninitLog);
}
@ -269,6 +300,11 @@ void VrLogUtils::EnableTime(bool bEnable)
/// 输出log
void VrLogUtils::EchoLog(VrLogLevel eLogLevel, const char* sFilePath, const int nLine, const char* sLogGroup, const char* sFormat, ...)
{
// 如果日志系统已关闭(程序退出),直接返回,不要重新初始化
if (g_isLogShutdown) {
return;
}
// 由于VrLogAutoCleaner会在程序启动时自动初始化这里只做保险检查
if (!g_isLogInitialized) {
InitLog();