fix(numerical): 捕获网格访问违例

- 为网格 DLL 调用增加访问违例捕获,异常时返回生成失败
- 失败时清理临时网格文件并释放 DLL,保留已有成果
- 启用 LM 拟合诊断轨迹
feature/Adapt-Autofit-20260904
lvjunjie 3 days ago
parent b7148fcfc9
commit 586a40df5c

@ -26,11 +26,7 @@
#define DEBUG_OUT(msg) OutputDebugStringA(QString("[AutoFitLM] %1\n").arg(msg).toLocal8Bit().data()) #define DEBUG_OUT(msg) OutputDebugStringA(QString("[AutoFitLM] %1\n").arg(msg).toLocal8Bit().data())
#endif #endif
#ifdef QT_NO_DEBUG
static const bool kAutoFitDiagnosticTraceEnabled = false;
#else
static const bool kAutoFitDiagnosticTraceEnabled = true; static const bool kAutoFitDiagnosticTraceEnabled = true;
#endif
static inline bool isFiniteNumber(double value) static inline bool isFiniteNumber(double value)
{ {
@ -687,7 +683,7 @@ void nmCalculationAutoFitLM::initializeTraceFile()
return; return;
} }
// 诊断轨迹仅在 Debug 构建中启用,并与源码、安装目录完全分离。 // 诊断轨迹在所有构建中启用,并与源码、安装目录完全分离。
if(m_traceRunId.isEmpty()) { if(m_traceRunId.isEmpty()) {
m_traceRunId = QString("%1-%2") m_traceRunId = QString("%1-%2")
.arg(QString::number(QCoreApplication::applicationPid())) .arg(QString::number(QCoreApplication::applicationPid()))

@ -36,6 +36,36 @@ namespace {
const int CONST_PVT_POINT_COUNT = 200; const int CONST_PVT_POINT_COUNT = 200;
typedef void (*HX_NWTM_GRID_Func)(
HX_NWTM_GRID_OUTPUT1&,
HX_NWTM_GRID_OUTPUT2&,
const HX_NWTM_GRID_INPUT&,
std::string);
__declspec(noinline) void invokePebiGridDll(
HX_NWTM_GRID_Func pfnGenerateGrid,
const nmPebiGridInputSnapshot& oSnapshot,
nmPebiGridResult& oResult)
{
// 单独调用网格 DLL避免字符串参数的构造、析构与异常捕获放在同一函数中导致编译错误。
pfnGenerateGrid(oResult.m_oGridOutput1, oResult.m_oGridOutput2,
oSnapshot.m_oGridInput, oSnapshot.m_sLicensePath.toStdString());
}
bool invokePebiGridDllGuarded(HX_NWTM_GRID_Func pfnGenerateGrid,
const nmPebiGridInputSnapshot& oSnapshot,
nmPebiGridResult& oResult)
{
// 仅拦截已复现的访问违例;普通 C++ 异常继续交给外层 catch堆损坏不在此恢复。
__try {
invokePebiGridDll(pfnGenerateGrid, oSnapshot, oResult);
} __except(GetExceptionCode() == EXCEPTION_ACCESS_VIOLATION
? EXCEPTION_EXECUTE_HANDLER : EXCEPTION_CONTINUE_SEARCH) {
return false;
}
return true;
}
// 该锁只保护 PEBI 网格单例缓存HX_NWTM.dll 的所有入口由独立进程级锁保护。 // 该锁只保护 PEBI 网格单例缓存HX_NWTM.dll 的所有入口由独立进程级锁保护。
// 保留递归锁以兼容可能在持锁网格入口中调用缓存查询的旧代码路径。 // 保留递归锁以兼容可能在持锁网格入口中调用缓存查询的旧代码路径。
QMutex s_oPebiGridMutex(QMutex::Recursive); QMutex s_oPebiGridMutex(QMutex::Recursive);
@ -1660,11 +1690,6 @@ bool nmCalculationPebiGrid::calculateSnapshot(
return false; return false;
} }
typedef void (*HX_NWTM_GRID_Func)(
HX_NWTM_GRID_OUTPUT1&,
HX_NWTM_GRID_OUTPUT2&,
const HX_NWTM_GRID_INPUT&,
std::string);
typedef int (*GetIntValueFunc)(); typedef int (*GetIntValueFunc)();
HX_NWTM_GRID_Func pfnGenerateGrid = HX_NWTM_GRID_Func pfnGenerateGrid =
@ -1687,10 +1712,13 @@ bool nmCalculationPebiGrid::calculateSnapshot(
} }
// 第二步DLL 输出先落在局部结果,失败时不清空单例缓存和已有成果。 // 第二步DLL 输出先落在局部结果,失败时不清空单例缓存和已有成果。
pfnGenerateGrid(oResult.m_oGridOutput1, if(!invokePebiGridDllGuarded(pfnGenerateGrid, oSnapshot, oResult)) {
oResult.m_oGridOutput2, // 本轮结果不再用于显示或求解,沿用现有失败通知保留旧成果。
oSnapshot.m_oGridInput, nmCalculationUtils::cleanupPebiGridDebugFiles();
oSnapshot.m_sLicensePath.toStdString()); FreeLibrary(hGridModule);
hGridModule = nullptr;
return false;
}
nmCalculationUtils::cleanupPebiGridDebugFiles(); nmCalculationUtils::cleanupPebiGridDebugFiles();
oResult.m_nPebiCount = pfnGetPebiCount(); oResult.m_nPebiCount = pfnGetPebiCount();

Loading…
Cancel
Save