refactor: 统一 XPrimData::m_pData 为字节数组,releaseData 只保留 delete[] #47

Merged
gjm merged 2 commits from company-desktop-computer/fix/ewequipment-memory-v2 AGit into main 2026-10-23 10:55:19 +08:00
2 changed files with 164 additions and 80 deletions
Showing only changes of commit 03bbe08b76 - Show all commits

No files matched your search

+75 -36
View File
@@ -109,7 +109,9 @@ void FreeBuffer(CPtrArray& arSubPrimPtrs) // :1520
被 `copyFrom:2181` 调用,于是 `copyFrom` 每次都泄漏被覆盖的那批 `XPrimData` 结构体。修 2.2 时会连带放大这个问题。
另外这里无条件 `delete[](byte*)`,而 `releaseData()` 是按类型区分 `delete[]` / `delete` 的。`byJson`(`:820`)用 `new PVOID[]` 分配,属于数组,`delete[]` 恰好对;但若将来有类型用标量 `new`,这里就是堆损坏。**建议统一改成 `pData->releaseData(); DELETE_PTR(pData);`**,让释放规则只有一处。
另外这里无条件 `delete[](byte*)`,而 `releaseData()` 是按类型区分 `delete[]` / `delete` 的。`byJson`(`:820`)用 `new PVOID[]` 分配,属于数组,`delete[]` 恰好对。
**修复时没有改用 `releaseData()`**:核实后发现 `releaseData()`(`EarThwormDef.h:2544`)的 `default` 分支用的是标量 `delete`,而 `m_pData` 的全部分配点(`copyXPrimData:150`、`dwgInFieldsForXPrim:193`、`byJson:820`、`:4472`)都是 `new byte[]` / `new PVOID[]`,标量 `delete` 反而与分配不匹配。所以本次统一走 `delete[](byte*)` + `DELETE_PTR(pData)`,封装成 `ReleaseXPrimData()` 供四处复用。`releaseData()` 自身这个不一致留待单独处理(它影响的是所有 `XPrimData` 的释放路径,不只是本文件)。
### 2.4 P0:`subDMesh2NewSolid()` 删错元素,且泄漏
@@ -193,19 +195,48 @@ delete pEnt; // :4049 只删了 exp
### 2.12 内存问题汇总
| 级别 | 问题 | 位置 | 触发频率 | 单次量级 |
| --- | --- | --- | --- | --- |
| P0 | 夹点数组重复分配 | `:1707` | 每个实体每次开图 | ~300 KB |
| P0 | 析构不释放几何单元 | `:1686` | 每个实体销毁 | 全部参数块 |
| P0 | `FreeBuffer` 不删结构体 | `:1520` | 每次 `copyFrom` | N 个结构体 |
| P0 | `subDMesh2NewSolid` 删错+泄漏 | `:3159` | 含 SubDMesh 的图 | N 个单元 + 几何错乱 |
| P1 | `RemoveSubPrimObj*` 漏 `releaseData` | `:4276` `:4291` | 编辑删除单元 | 1 个参数块 |
| P1 | `GetDraw2dables` 克隆泄漏 | `:2850` `:2857` | 2D 导出/剖切 | N 个 solid |
| P1 | 剖切克隆泄漏 | `:12691` `:12620` | 每次剖切 | N 个实体 |
| P1 | `readString` 未释放 | `:1720` | 每次开图 | 小 |
| P1 | `convertToRegion` 泄漏 | `:4032` | 最近点查询 | N 个 region |
| P2 | 空曲线丢弃 | `:11240` | 每次 2D 投影 | 小 |
| P2 | `ByJson` / `MakeBlockRefSet` 失败路径 | `:12853` `:12540` | 异常路径 | 小 |
| 级别 | 问题 | 位置 | 触发频率 | 单次量级 | 状态 |
| --- | --- | --- | --- | --- | --- |
| P0 | 夹点数组重复分配 | `:1707` | 每个实体每次开图 | ~300 KB | 已修 |
| P0 | 析构不释放几何单元 | `:1686` | 每个实体销毁 | 全部参数块 | 已修 |
| P0 | `FreeBuffer` 不删结构体 | `:1520` | 每次 `copyFrom` | N 个结构体 | 已修 |
| P0 | `subDMesh2NewSolid` 删错+泄漏 | `:3159` | 含 SubDMesh 的图 | N 个单元 + 几何错乱 | 已修 |
| P1 | `RemoveSubPrimObj*` 漏 `releaseData` | `:4276` `:4291` | 编辑删除单元 | 1 个参数块 | 已修 |
| P1 | `GetDraw2dables` 克隆泄漏 | `:2850` `:2857` | 2D 导出/剖切 | N 个 solid | 已修 |
| P1 | 剖切克隆泄漏 | `:12691` `:12620` | 每次剖切 | N 个实体 | 已修 |
| P1 | `readString` 未释放 | `:1720` | 每次开图 | 小 | 已修 |
| P1 | `convertToRegion` 泄漏 | `:4032` | 最近点查询 | N 个 region | 已修 |
| P1 | `GetDraw3dables` 合并后不删入参 | `:2975` | 每次导出 3D | N 个 solid | 已修 |
| P2 | 空曲线丢弃 | `:11240` | 每次 2D 投影 | 小 | 已修 |
| P2 | `ByJson` / `MakeBlockRefSet` 失败路径 | `:12853` `:12540` | 异常路径 | 小 | 已修 |
“已修”的改动见 2.13。
### 2.13 第一批内存修复的实施记录
改动集中在 `CoreLibrary/AecDbEwEquipment.cpp`,不涉及头文件和存储格式。
| # | 实际改法 | 与原方案的差异 |
| --- | --- | --- |
| 1 | 删掉 `dwgInFields` 里的 `new AecGripData[GRIP_MAXNUM]`;`readString` 后补 `acutDelString(pszTmp)` | 同原方案 |
| 2 | 析构补 `FreeBuffer(m_arSubPrimPtrs)` | 同原方案 |
| 3 | 新增 `ReleaseXPrimData()`(匿名 namespace),`FreeBuffer(CPtrArray&)` 改为调用它 | 没用 `releaseData()`,原因见 2.3 |
| 4 | `subDMesh2NewSolid()` 按 `idxs` 倒序 `ReleaseXPrimData` + `RemoveAt` | 同原方案,另把 `size_t i` 改成 `int i` 倒序 |
| 5 | `RemoveSubPrimObj` / `RemoveSubPrimObjByID` 改用 `ReleaseXPrimData` | 同原方案 |
| 6 | `GetDraw2dables` 两个 `continue` 前补 `DELETE_PTR(pClnEnt)` | 同原方案 |
| 7 | `OldGetSectionDraw` 循环内补 `DELETE_PTR(pSubCln)`、循环后补 `FreeBuffer(arSubPtrs)`;`GetSectionDraw` 两处 `return OldGetSectionDraw` 前补 `delete pFit` | 同原方案 |
| 8 | `convertToRegion` 的 `regions` 循环结束后逐个 `DELETE_PTR`;顺带把内层遮蔽的 `i` 改为 `j` | 同原方案 |
| 9 | `SortAecComplexCurves` 空曲线改为 `DELETE_PTR` | 同原方案,另补 `pCrv == NULL` 判断 |
| 10 | `ByJson` 循环前 `FreeBuffer(m_arSubPrimPtrs)`,`byJson` 失败时 `ReleaseXPrimData(p)` | 同原方案 |
| 11 | `MakeBlockRefSet` 的 `getBlockTable` / `pTbl->add` 失败时 `pRec->close()` 并返回 `false` | 同原方案 |
| 12 | `dwgInFields` 的 `m_arSubPrimPtrs.RemoveAll()` 改为 `FreeBuffer` | 新增,原注释写着 FreeBufer 但没真释放 |
| 13 | `GetDraw3dables` 的 `booleanOper(kBoolUnite)` 之后补 `DELETE_PTR(pSolid)` | 新增,见 3.15 |
**尚未处理**:
- 2.8 的第二个问题(为了算最近点把临时 solid 写进模型空间再 erase),属于副作用与性能,放在第三批
- `~XPrimData()`(`EarThwormDef.h:2539`)只删 `m_Combins` 里的结构体,不释放它们的 `m_pData`。这条要动公共头文件,且只影响 `kCombination` 单元(存盘时又会被 3.1 清空),单独评估
---
@@ -365,11 +396,16 @@ for (...) {
| 位置 | 写法 | 若 SDK 会删除入参 | 若 SDK 不删除入参 |
| --- | --- | --- | --- |
| `:3774` | `booleanOper(...); DELETE_PTR(p);` | 二次释放 | 正确 |
| `:3867` `:3964` | `booleanOper(...)` 后统一 `deleteArrayVoidPtrs` | 二次释放 | 正确 |
| `:2964` | `booleanOper(kBoolUnite, pSolid)`,克隆体不再处理 | 正确 | 每次泄漏一个克隆 |
| `:3790` | `booleanOper(...); DELETE_PTR(p);` | 二次释放 | 正确 |
| `:3883` `:3980` | `booleanOper(...)` 后统一 `deleteArrayVoidPtrs` | 二次释放 | 正确 |
| `:14198` | `booleanOper(...); DELETE_PTR(pSolid);` | 二次释放 | 正确 |
| `:2975` | `booleanOper(kBoolUnite, pSolid)`,克隆体不再处理 | 正确 | 每次泄漏一个克隆 |
也就是说:**无论 SDK 语义是哪一种,这三处至少有一处是错的**。需要先用最小样例(两个 box 做 unite,然后只删第二个)在调试版 + Application Verifier 下确认,再统一写法。这条不确认,2.6 和 2.7 的修复方式都不好定。
本文件 5 处调用里 4 处都主动释放入参,`:2975` 是唯一的例外。
**2026-10-23 结论**:按「`booleanOper` 不删除入参」处理,`:2975` 补 `DELETE_PTR(pSolid)`(见 2.13 #13)。依据是同一文件另外 4 处(含失败路径 `:2002` 的 `DELETE_PTR(pSolidInside)`)都按调用方负责释放来写;若 SDK 实际会删除入参,这些既有代码早就在正常流程里二次释放崩掉了。
另外 `CoreLibrary/AcDbX3dSolid.cpp:1998` 的 `booleanOper` 成功路径没有释放 `pSolidInside`,同一约定下也是一个泄漏点,不在本次范围。
### 3.16 其他
@@ -468,21 +504,23 @@ Draw3dSolid(&dc, nColor); // :3062 拖拽时每帧都走到这里
### 5.1 第一批:内存与正确性(不改接口、不改格式)
| # | 改动 | 位置 | 风险 |
| --- | --- | --- | --- |
| 1 | 删掉 `dwgInFields` 里的重复分配,`readString` 补 `acutDelString` | `:1707` `:1720` | 低 |
| 2 | 析构补 `FreeBuffer(m_arSubPrimPtrs)` | `:1686` | 低(依赖 #3) |
| 3 | `FreeBuffer(CPtrArray&)` 改为 `releaseData()` + `DELETE_PTR` | `:1520` | 低 |
| 4 | `subDMesh2NewSolid` 按下标倒序删除并释放 | `:3159` | 中(涉及几何正确性,需样例图) |
| 5 | `RemoveSubPrimObj*` 补 `releaseData()` | `:4276` `:4291` | 低 |
| 6 | `subErase` 的 `Find` 补 `!= -1` | `:2119` | 低(行为会变,需回归删除阀门) |
| 7 | `DrawHandFlg` 的 `==` 改 `=` | `:2656` | 低 |
| 8 | `ProcessHlrResult` 改用 `it = erase(it)` | `:13128` | 低 |
| 9 | `copyFrom` 补 `m_bVert` / `m_idDash` / `m_idCenter` | `:2174` | 低 |
| 10 | `GetSectionDraw` 返回值改 `nCoundPre - nCount` | `:12762` | 低(需确认调用方语义) |
| 11 | `clearGeoBuffer` 实现为清 2D/3D 缓存 | `:12861` | 低 |
拆成两批提交:**内存问题已做(见 2.13)**,逻辑缺陷待做。
这一批做完,开图内存和几个明确的逻辑错误就都清掉了,且不触碰存储格式。
| # | 改动 | 位置 | 风险 | 状态 |
| --- | --- | --- | --- | --- |
| 1 | 删掉 `dwgInFields` 里的重复分配,`readString` 补 `acutDelString` | `:1707` `:1720` | 低 | 已完成 |
| 2 | 析构补 `FreeBuffer(m_arSubPrimPtrs)` | `:1686` | 低(依赖 #3) | 已完成 |
| 3 | `FreeBuffer(CPtrArray&)` 释放 `m_pData` 后删结构体 | `:1520` | 低 | 已完成(未用 `releaseData`,见 2.3) |
| 4 | `subDMesh2NewSolid` 按下标倒序删除并释放 | `:3159` | 中(涉及几何正确性,需样例图) | 已完成 |
| 5 | `RemoveSubPrimObj*` 补释放 `m_pData` | `:4276` `:4291` | 低 | 已完成 |
| 6 | `subErase` 的 `Find` 补 `!= -1` | `:2119` | 低(行为会变,需回归删除阀门) | 待做 |
| 7 | `DrawHandFlg` 的 `==` 改 `=` | `:2656` | 低 | 待做 |
| 8 | `ProcessHlrResult` 改用 `it = erase(it)` | `:13128` | 低 | 待做 |
| 9 | `copyFrom` 补 `m_bVert` / `m_idDash` / `m_idCenter` | `:2174` | 低 | 待做 |
| 10 | `GetSectionDraw` 返回值改 `nCoundPre - nCount` | `:12762` | 低(需确认调用方语义) | 待做 |
| 11 | `clearGeoBuffer` 实现为清 2D/3D 缓存 | `:12861` | 低 | 待做 |
另外补做的 4 处内存修复(2.6、2.7、2.9、2.10、2.11、`GetDraw3dables` 合并泄漏、`dwgInFields` 的 `RemoveAll`)见 2.13。
### 5.2 第二批:`m_Combins` 存盘清空(需要确认影响面)
@@ -507,7 +545,7 @@ Draw3dSolid(&dc, nColor); // :3062 拖拽时每帧都走到这里
### 5.4 需要先确认的事
1. `booleanOper` 是否删除入参(3.15)—— 决定 2.6 / 2.7 怎么修
1. ~~`booleanOper` 是否删除入参(3.15)~~ —— 2026-10-23 按「不删除入参」处理,理由见 3.15
2. `GetSectionDraw` 的返回值调用方到底期望什么(3.5)
3. `PreprocessForHlr` 的 `mat4` 双次变换是否刻意(3.12)
4. `kCombination` 单元的实际存量(5.2)
@@ -519,7 +557,8 @@ Draw3dSolid(&dc, nColor); // :3062 拖拽时每帧都走到这里
| 改动 | 验证方式 |
| --- | --- |
| 夹点数组 / 析构释放 | 打开含 1000+ 设备的图纸,任务管理器看私有字节;关图后应回落 |
| `FreeBuffer` 改 `releaseData` | 各类单元(box/cylinder/cone/Revit/组合)各删一个,确认无崩溃 |
| `FreeBuffer` 释放结构体 | 各类单元(box/cylinder/cone/Revit/组合)各删一个,确认无崩溃 |
| 剖切 / 2D 导出 | 对含阀门、法兰、普通设备的图各剖一次,反复开关剖切对话框,内存不持续上涨 |
| `subDMesh2NewSolid` | 含 SubDMesh 的样例图,开图后单元数量与类型正确,绘制不缺体 |
| `subErase` | 删除阀门/接头/普通设备各一次,确认只有阀门走合并管线 |
| `HLR_CALC` | 剖切过程中保存再重开,设备 3D 仍可见 |
@@ -541,8 +580,8 @@ Draw3dSolid(&dc, nColor); // :3062 拖拽时每帧都走到这里
## 8. 实施顺序
1. 第一批 1~5(内存),单独一个 PR,可独立验证
1. ~~第一批 1~5(内存),单独一个 PR,可独立验证~~ —— 已完成,范围扩到 2.1~2.11 全部内存项,见 2.13
2. 第一批 6~11(逻辑),单独一个 PR
3. 确认 5.4 的四个问题
3. 确认 5.4 剩下的三个问题
4. 第二批(`m_Combins`),视存量决定是否做
5. 第三批按 4.7 度量结果排序,一项一个 PR
@@ -169,6 +169,19 @@ namespace
return pData;
}
//释放一个几何单元。m_pData 在 copyXPrimData、dwgInFieldsForXPrim、byJson
//等处一律用 new byte[] / new PVOID[] 分配,必须用 delete[],再删结构体本身
void ReleaseXPrimData(AecEqui::XPrimData* pData)
{
if (pData == NULL) return;
if (pData->m_pData != NULL)
{
delete[](byte*)pData->m_pData;
pData->m_pData = NULL;
}
DELETE_PTR(pData);
}
AecEqui::XPrimData* dwgInFieldsForXPrim(AcDbDwgFiler *pFiler, const Adesk::UInt32 &CurrentVer)
{
Adesk::Int16 nType = 0;
@@ -1521,14 +1534,8 @@ namespace
{
for (int i = 0; i < arSubPrimPtrs.GetSize(); i++)
{
AecEqui::XPrimData* pData = (AecEqui::XPrimData*)arSubPrimPtrs.GetAt(i);
if (pData != NULL)
{
if (pData->m_nSize > 0)
{
delete[](byte*)pData->m_pData;
}
}
//原来只 delete[] m_pData、不删结构体,结构体全部泄漏
ReleaseXPrimData((AecEqui::XPrimData*)arSubPrimPtrs.GetAt(i));
}
arSubPrimPtrs.RemoveAll();
}
@@ -1687,6 +1694,7 @@ AecDbEwEquipment::~AecDbEwEquipment(void)
{
Clean3DBuffer();
Clean2DBuffer();
FreeBuffer(m_arSubPrimPtrs);
delete [] m_pGripAppData;
}
@@ -1704,7 +1712,7 @@ Acad::ErrorStatus AecDbEwEquipment::dwgInFields(AcDbDwgFiler* pFiler)
}
//----- Object version number needs to be read first
m_pGripAppData = new AecGripData[GRIP_MAXNUM];
//夹点数组由构造函数分配,此处不要再分配一次,否则旧数组直接泄漏(约 300KB/实体)
Adesk::UInt32 version = 0;
if ((es = pFiler->readUInt32(&version)) != Acad::eOk)
return (es);
@@ -1721,6 +1729,7 @@ Acad::ErrorStatus AecDbEwEquipment::dwgInFields(AcDbDwgFiler* pFiler)
if (pszTmp != NULL)
{
m_sGUID = pszTmp;
acutDelString(pszTmp);
}
//////////////////////////////////////////////////////////////////////////
@@ -1728,8 +1737,8 @@ Acad::ErrorStatus AecDbEwEquipment::dwgInFields(AcDbDwgFiler* pFiler)
Adesk::Int32 nLen = 0;
pFiler->readInt32(&nLen);
//FreeBufer
m_arSubPrimPtrs.RemoveAll();
//重新读入前先释放旧几何,只 RemoveAll 会漏掉结构体和参数块
FreeBuffer(m_arSubPrimPtrs);
AecEqui::XPrimData* pSolid = NULL;
Adesk::Int16 nType = 0;
@@ -2848,6 +2857,7 @@ int AecDbEwEquipment::GetDraw2dables(Adesk::UInt16 nDrawStyle, AcDbVoidPtrArray&
{
//投影法
OrthoProjected3DSolid(pSolid,plan,xform,arSubEntPtrs);
DELETE_PTR(pClnEnt); //投影函数不接管所有权,原来直接 continue 导致克隆体泄漏
continue;
}
@@ -2855,6 +2865,7 @@ int AecDbEwEquipment::GetDraw2dables(Adesk::UInt16 nDrawStyle, AcDbVoidPtrArray&
if (pSubMesh != NULL)
{
OrthoProjected3DSubMesh(pSubMesh,plan,xform,arSubEntPtrs);
DELETE_PTR(pClnEnt);
continue;
}
@@ -2962,6 +2973,8 @@ int AecDbEwEquipment::GetDraw3dables(AcDbVoidPtrArray& arEntPtrs,bool bWriteBimI
else
{
pSolidAll->booleanOper(AcDb::kBoolUnite,pSolid);
//booleanOper 不接管入参,原来每个被合并掉的克隆体都泄漏
DELETE_PTR(pSolid);
}
}
else
@@ -3156,9 +3169,12 @@ void AecDbEwEquipment::subDMesh2NewSolid()
}
}
for (size_t i(0); i < idxs.size(); ++i)
//必须倒序删除:idxs 里存的是删除前的原始下标,正序删会让后面的下标整体前移
for (int i((int)idxs.size() - 1); i >= 0; --i)
{
m_arSubPrimPtrs.RemoveAt(i);
int nIndex = idxs[i];
ReleaseXPrimData((AecEqui::XPrimData *)m_arSubPrimPtrs[nIndex]);
m_arSubPrimPtrs.RemoveAt(nIndex);
}
m_arSubPrimPtrs.Append(ar);
@@ -4031,9 +4047,9 @@ bool AecDbEwEquipment::GetClosestPointToSUbPrim(DWORD dwSubiD, AcGePoint3d& ptNe
AcArray<AcDbEntity *> regions;
pFace->convertToRegion(regions);
for (int i = 0; i < regions.length(); i++)
for (int j = 0; j < regions.length(); j++)
{
AcDbRegion *pIn = (AcDbRegion *)regions.at(i);
AcDbRegion *pIn = (AcDbRegion *)regions.at(j);
CoreTools::getRegionInfo(pIn, ptC, dA, pln);
@@ -4045,6 +4061,10 @@ bool AecDbEwEquipment::GetClosestPointToSUbPrim(DWORD dwSubiD, AcGePoint3d& ptNe
mpPns.insert(std::make_pair(pn.dDis, pn));
}
//convertToRegion 产出的 region 归调用方所有,原来一个都没释放
for (int j = 0; j < regions.length(); j++)
DELETE_PTR(regions[j]);
}
delete pEnt;
}
@@ -4273,7 +4293,7 @@ void AecDbEwEquipment::RemoveSubPrimObj(int nIndex)
pSolid = (AecEqui::XPrimData*)m_arSubPrimPtrs.GetAt(nIndex);
m_arSubPrimPtrs.RemoveAt(nIndex);
m_mapSpecXData.RemoveAt(TypeConvert::i2s(pSolid->m_nID) + _T(":color"));
DELETE_PTR(pSolid);
ReleaseXPrimData(pSolid);
}
}
@@ -4288,7 +4308,7 @@ void AecDbEwEquipment::RemoveSubPrimObjByID(int nSubID)
{
m_arSubPrimPtrs.RemoveAt(i);
m_mapSpecXData.RemoveAt(TypeConvert::i2s(pSolid->m_nID) + _T(":color"));
DELETE_PTR(pSolid);
ReleaseXPrimData(pSolid);
break;
}
}
@@ -11233,7 +11253,11 @@ void AecDbEwEquipment::SortAecComplexCurves(CPtrArray& arPrimCplPtrs) const
for (int i = 0; i < arPrimCplPtrs.GetSize(); i++)
{
AecComplexCurve* pCrv = (AecComplexCurve*)arPrimCplPtrs.GetAt(i);
if (pCrv->length() > 0) vtComplexcrv.push_back(pCrv);
if (pCrv == NULL) continue;
if (pCrv->length() > 0)
vtComplexcrv.push_back(pCrv);
else
DELETE_PTR(pCrv); //空曲线原来被直接丢弃,泄漏
}
std::sort(vtComplexcrv.begin(), vtComplexcrv.end(), CompareComplexcrvByZ);
@@ -12556,35 +12580,44 @@ DLLIMPEXP bool MakeBlockRefSet(AcDbVoidPtrArray& arEntPtrs,const AcDbObjectId& i
AcDbObjectId idRec;
AcDbBlockTable *pTbl = NULL;
if (Acad::eOk == pDb->getBlockTable(pTbl, AcDb::kForWrite))
if (Acad::eOk != pDb->getBlockTable(pTbl, AcDb::kForWrite) || pTbl == NULL)
{
pTbl->add(idRec, pRec);
pTbl->close();
TCHAR szHd[17];
idRec.handle().getIntoAsciiBuffer(szHd);
if (_tcscmp(pszName, _T("*U")) == 0 ||
_tcscmp(pszName, _T("*u")) == 0)
{
}
else
{
sName.Format(_T("%s@%s"), pszName, szHd);
Acad::ErrorStatus es = pRec->setName(sName);
}
//原来这里直接跳过,pRec 既不关闭也不删除,每次调用泄漏一个块表记录
pRec->close();
return false;
}
if (idRec.isValid())
{
AcDbBlockReference *pRef = new AcDbBlockReference;
pRef->setBlockTableRecord(idRec);
pRef->setRotation(0);
pRef->setPosition(ptIns);
pRef->setLayer(idLay);
arEntPtrs.append(pRef);
}
Acad::ErrorStatus esAdd = pTbl->add(idRec, pRec);
pTbl->close();
if (esAdd != Acad::eOk)
{
pRec->close();
return false;
}
TCHAR szHd[17];
idRec.handle().getIntoAsciiBuffer(szHd);
if (_tcscmp(pszName, _T("*U")) == 0 ||
_tcscmp(pszName, _T("*u")) == 0)
{
}
else
{
sName.Format(_T("%s@%s"), pszName, szHd);
Acad::ErrorStatus es = pRec->setName(sName);
}
pRec->close();
if (idRec.isValid())
{
AcDbBlockReference *pRef = new AcDbBlockReference;
pRef->setBlockTableRecord(idRec);
pRef->setRotation(0);
pRef->setPosition(ptIns);
pRef->setLayer(idLay);
arEntPtrs.append(pRef);
}
return true;
}
@@ -12624,8 +12657,12 @@ bool AecDbEwEquipment::OldGetSectionDraw(AcGePlane &plan, const AcGeVector3d &vt
{
OrthoProjected3DSolid(pSolidT, plan, xform, arProPtrs);
}
//非 solid 的克隆体原来既不进结果也不释放
DELETE_PTR(pSubCln);
}
}
//GetDraw3dables 产出的整组克隆,原来从头到尾没释放
FreeBuffer(arSubPtrs);
CString sName;
m_mapSpecXData.GetAt(KEY_NAME, sName);
@@ -12688,6 +12725,7 @@ bool AecDbEwEquipment::GetSectionDraw(AcGePlane& plan,const AcGeVector3d& vtTo,A
//不是2个接口,走投影,不画符号
if (pFit->GetInterfaceCount() != 2)
{
delete pFit; //原来直接 return,克隆出来的整份设备泄漏
return OldGetSectionDraw(plan, vtTo, arRegionPtrs);
}
@@ -12739,6 +12777,7 @@ bool AecDbEwEquipment::GetSectionDraw(AcGePlane& plan,const AcGeVector3d& vtTo,A
}
else//不是阀门,其他设备
{
delete pFit;
return OldGetSectionDraw(plan, vtTo, arRegionPtrs);
}
}
@@ -12848,11 +12887,17 @@ bool AecDbEwEquipment::ByJson(const SHJson::WValue &v)
it = v.FindMember(_T("__arSubPrimPtrs__"));
if (it == v.MemberEnd()) return false;
if (!it->value.IsArray()) return false;
//先释放旧几何,否则对已有对象再导入会叠加重复单元
FreeBuffer(m_arSubPrimPtrs);
for (VCIt i = it->value.Begin(); i != it->value.End(); ++i)
{
AecEqui::XPrimData *p = new AecEqui::XPrimData;
if (byJson(*i, p))
m_arSubPrimPtrs.Add(p);
else
ReleaseXPrimData(p); //解析失败,原来既不进数组也不释放
}
return true;