refactor: 统一 XPrimData::m_pData 为字节数组,releaseData 只保留 delete[] #47
No files matched your search
+103
-37
@@ -89,7 +89,7 @@ AecDbEwEquipment::~AecDbEwEquipment(void) // :1686
|
||||
|
||||
同类 `AecDbEwFitting` 的析构(`:584`)同样没处理它的子单元数组,属于同一批遗留写法。
|
||||
|
||||
**修复**:析构里补 `FreeBuffer(m_arSubPrimPtrs);`(该函数已存在,见 2.3,需先修 2.3)。
|
||||
**修复**:析构里补 `FreeSubPrimData();`(成员函数,见 2.3 与 2.13)。
|
||||
|
||||
### 2.3 P0:`FreeBuffer(CPtrArray&)` 只释放数据块,不释放结构体
|
||||
|
||||
@@ -109,7 +109,28 @@ 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` 的。
|
||||
|
||||
**核查 `m_pData` 的全部分配点后,结论是 `releaseData()` 的类型判断不可靠**——同一个类型在内存里可能是对象,也可能是字节数组:
|
||||
|
||||
| 来源 | 分配形式 |
|
||||
| --- | --- |
|
||||
| `dwgInFieldsForXPrim:206`(开图) | `new byte[n]`,所有类型 |
|
||||
| `byJson:833`(JSON 导入) | `new PVOID[n]`,所有类型 |
|
||||
| `copyXPrimData:150`(深拷贝) | `new byte[n]`,所有类型 |
|
||||
| `CoreTools.cpp:2036` / `:4565` / `:4662` | `new byte[]` / `new char[]` |
|
||||
| 各命令模块的 `setData<T>`(8 处) | `kExtrude`/`kRevolve` 用 `new byte[]`,其余 `new T` |
|
||||
| `PipelineCmd/command.cpp:18670` 等 5 处 | `new AecEqui::XNozz` / `new AecEqui::XBOX` |
|
||||
|
||||
例如 `kBox` 从对话框创建时是 `new AecEqui::XBOX`,开图读回时却是 `new byte[]`。按 `m_eType` 判断,必然有一半场景不匹配(MSVC 下 POD 数组的 `delete` 与 `delete[]` 实际都走 `free`,所以一直没暴露)。
|
||||
|
||||
**改法:统一表示,再统一释放规则。**
|
||||
|
||||
1. 把 13 处对象形式的分配改成 `new unsigned char[sizeof(T)]`(`sizeof(T)` 与原来一致,后续 `(T*)m_pData` 的用法不变)
|
||||
2. `releaseData()` 去掉 switch,只保留 `delete[] (unsigned char*)m_pData`
|
||||
3. `~XPrimData()` 改为先调 `releaseData()`,顺带修掉 `m_Combins` 子单元的 `m_pData` 泄漏
|
||||
|
||||
这样 `AecDbEwEquipment.cpp` 里的 `ReleaseXPrimData` 就不需要了,直接 `pData->releaseData(); DELETE_PTR(pData);`。
|
||||
|
||||
### 2.4 P0:`subDMesh2NewSolid()` 删错元素,且泄漏
|
||||
|
||||
@@ -193,19 +214,56 @@ 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 | 析构补 `FreeSubPrimData()` | 同原方案 |
|
||||
| 3 | `FreeSubPrimData()` 成员函数:逐个 `releaseData()` + `DELETE_PTR`,最后 `RemoveAll` | 见 2.3,先统一了 `m_pData` 表示 |
|
||||
| 4 | `subDMesh2NewSolid()` 按 `idxs` 倒序释放 + `RemoveAt` | 同原方案,另把 `size_t i` 改成 `int i` 倒序 |
|
||||
| 5 | `RemoveSubPrimObj` / `RemoveSubPrimObjByID` 改用 `releaseData()` + `DELETE_PTR` | 同原方案 |
|
||||
| 6 | `GetDraw2dables` 两个 `continue` 前补 `DELETE_PTR(pClnEnt)` | 同原方案 |
|
||||
| 7 | `OldGetSectionDraw` 循环内补 `DELETE_PTR(pSubCln)`、循环后补 `FreeEntityArray(arSubPtrs)`;`GetSectionDraw` 两处 `return OldGetSectionDraw` 前补 `delete pFit` | 同原方案 |
|
||||
| 8 | `convertToRegion` 的 `regions` 循环结束后逐个 `DELETE_PTR`;顺带把内层遮蔽的 `i` 改为 `j` | 同原方案 |
|
||||
| 9 | `SortAecComplexCurves` 空曲线改为 `DELETE_PTR` | 同原方案,另补 `pCrv == NULL` 判断 |
|
||||
| 10 | `ByJson` 循环前 `FreeSubPrimData()`,`byJson` 失败时 `releaseData()` + `DELETE_PTR` | 同原方案 |
|
||||
| 11 | `MakeBlockRefSet` 的 `getBlockTable` / `pTbl->add` 失败时 `pRec->close()` 并返回 `false` | 同原方案 |
|
||||
| 12 | `dwgInFields` 的 `m_arSubPrimPtrs.RemoveAll()` 改为 `FreeSubPrimData()` | 新增,原注释写着 FreeBufer 但没真释放 |
|
||||
| 13 | `GetDraw3dables` 的 `booleanOper(kBoolUnite)` 之后补 `DELETE_PTR(pSolid)` | 新增,见 3.15 |
|
||||
|
||||
**函数命名整理**(`AecDbEwEquipment.cpp` 原来有 4 个文件作用域、外部链接的 `FreeBuffer*`,与其他 cpp 里的同名 `static` 函数容易混淆):
|
||||
|
||||
| 原名 | 现名 | 说明 |
|
||||
| --- | --- | --- |
|
||||
| `FreeBuffer(CPtrArray&)` | `AecDbEwEquipment::FreeSubPrimData()` | 只处理 `m_arSubPrimPtrs`,改成成员函数后参数不再需要 |
|
||||
| `FreeBuffer(AcDbVoidPtrArray&)` | `static FreeEntityArray()` | 通用实体数组,加 `static` 收回内部链接 |
|
||||
| `FreeBuffer2(CPtrArray&)` | `static FreeComplexCurveArray()` | `AecComplexCurve` 数组 |
|
||||
| `FreeBuffer3(CPtrArray&)` | `static FreeFaceplanArray()` | `Aec3dFaceplan` 数组 |
|
||||
|
||||
**尚未处理**:
|
||||
|
||||
- 2.8 的第二个问题(为了算最近点把临时 solid 写进模型空间再 erase),属于副作用与性能,放在第三批
|
||||
|
||||
|
||||
---
|
||||
|
||||
@@ -365,11 +423,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 +531,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 | 析构补 `FreeSubPrimData()` | `:1686` | 低(依赖 #3) | 已完成 |
|
||||
| 3 | `releaseData()` 统一 `delete[]`,`FreeSubPrimData()` 释放 `m_pData` 后删结构体 | `:1520` | 低 | 已完成(见 2.3、2.13) |
|
||||
| 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 +572,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 +584,8 @@ Draw3dSolid(&dc, nColor); // :3062 拖拽时每帧都走到这里
|
||||
| 改动 | 验证方式 |
|
||||
| --- | --- |
|
||||
| 夹点数组 / 析构释放 | 打开含 1000+ 设备的图纸,任务管理器看私有字节;关图后应回落 |
|
||||
| `FreeBuffer` 改 `releaseData` | 各类单元(box/cylinder/cone/Revit/组合)各删一个,确认无崩溃 |
|
||||
| `releaseData` 统一 `delete[]` | 各类单元(box/cylinder/cone/Revit/组合)各删一个,确认无崩溃;开图→改参数→存盘→重开,几何完整 |
|
||||
| 剖切 / 2D 导出 | 对含阀门、法兰、普通设备的图各剖一次,反复开关剖切对话框,内存不持续上涨 |
|
||||
| `subDMesh2NewSolid` | 含 SubDMesh 的样例图,开图后单元数量与类型正确,绘制不缺体 |
|
||||
| `subErase` | 删除阀门/接头/普通设备各一次,确认只有阀门走合并管线 |
|
||||
| `HLR_CALC` | 剖切过程中保存再重开,设备 3D 仍可见 |
|
||||
@@ -541,8 +607,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
|
||||
@@ -871,7 +871,7 @@ namespace
|
||||
}
|
||||
|
||||
#pragma region
|
||||
void FreeBuffer2(CPtrArray& arCplptrs)
|
||||
static void FreeComplexCurveArray(CPtrArray& arCplptrs)
|
||||
{
|
||||
for (int i = 0; i < arCplptrs.GetSize(); i++)
|
||||
{
|
||||
@@ -884,7 +884,7 @@ namespace
|
||||
arCplptrs.RemoveAll();
|
||||
}
|
||||
|
||||
void FreeBuffer3(CPtrArray& arCplptrs)
|
||||
static void FreeFaceplanArray(CPtrArray& arCplptrs)
|
||||
{
|
||||
for (int i = 0; i < arCplptrs.GetSize(); i++)
|
||||
{
|
||||
@@ -1506,7 +1506,7 @@ namespace
|
||||
return bOk;
|
||||
}
|
||||
|
||||
void FreeBuffer(AcDbVoidPtrArray& arEntPtrs)
|
||||
static void FreeEntityArray(AcDbVoidPtrArray& arEntPtrs)
|
||||
{
|
||||
AcDbEntity* pEnt = NULL;
|
||||
while (arEntPtrs.length() > 0)
|
||||
@@ -1517,22 +1517,6 @@ namespace
|
||||
}
|
||||
}
|
||||
|
||||
void FreeBuffer(CPtrArray& arSubPrimPtrs)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
arSubPrimPtrs.RemoveAll();
|
||||
}
|
||||
|
||||
void TransformEntity(AcDbEntity *p
|
||||
, const AcGePoint3d &ptIns
|
||||
, const AcGeVector3d &vtDir
|
||||
@@ -1687,6 +1671,7 @@ AecDbEwEquipment::~AecDbEwEquipment(void)
|
||||
{
|
||||
Clean3DBuffer();
|
||||
Clean2DBuffer();
|
||||
FreeSubPrimData();
|
||||
delete [] m_pGripAppData;
|
||||
}
|
||||
|
||||
@@ -1704,7 +1689,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 +1706,7 @@ Acad::ErrorStatus AecDbEwEquipment::dwgInFields(AcDbDwgFiler* pFiler)
|
||||
if (pszTmp != NULL)
|
||||
{
|
||||
m_sGUID = pszTmp;
|
||||
acutDelString(pszTmp);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -1728,8 +1714,8 @@ Acad::ErrorStatus AecDbEwEquipment::dwgInFields(AcDbDwgFiler* pFiler)
|
||||
Adesk::Int32 nLen = 0;
|
||||
pFiler->readInt32(&nLen);
|
||||
|
||||
//FreeBufer
|
||||
m_arSubPrimPtrs.RemoveAll();
|
||||
//重新读入前先释放旧几何,只 RemoveAll 会漏掉结构体和参数块
|
||||
FreeSubPrimData();
|
||||
AecEqui::XPrimData* pSolid = NULL;
|
||||
|
||||
Adesk::Int16 nType = 0;
|
||||
@@ -2177,9 +2163,8 @@ Acad::ErrorStatus AecDbEwEquipment::copyFrom(const AcRxObject* pSrc)
|
||||
|
||||
AecDbEntityBase::copyFrom(pSrc);
|
||||
|
||||
//FreeBufer!!!!
|
||||
FreeBuffer(m_arSubPrimPtrs);
|
||||
m_arSubPrimPtrs.RemoveAll();
|
||||
//先释放旧几何,否则被覆盖的那批结构体和参数块全部泄漏
|
||||
FreeSubPrimData();
|
||||
|
||||
AecDbEwEquipment* pImp = (AecDbEwEquipment*)pSrc;
|
||||
if (pImp != NULL)
|
||||
@@ -2848,6 +2833,7 @@ int AecDbEwEquipment::GetDraw2dables(Adesk::UInt16 nDrawStyle, AcDbVoidPtrArray&
|
||||
{
|
||||
//投影法
|
||||
OrthoProjected3DSolid(pSolid,plan,xform,arSubEntPtrs);
|
||||
DELETE_PTR(pClnEnt); //投影函数不接管所有权,原来直接 continue 导致克隆体泄漏
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2855,6 +2841,7 @@ int AecDbEwEquipment::GetDraw2dables(Adesk::UInt16 nDrawStyle, AcDbVoidPtrArray&
|
||||
if (pSubMesh != NULL)
|
||||
{
|
||||
OrthoProjected3DSubMesh(pSubMesh,plan,xform,arSubEntPtrs);
|
||||
DELETE_PTR(pClnEnt);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -2962,6 +2949,8 @@ int AecDbEwEquipment::GetDraw3dables(AcDbVoidPtrArray& arEntPtrs,bool bWriteBimI
|
||||
else
|
||||
{
|
||||
pSolidAll->booleanOper(AcDb::kBoolUnite,pSolid);
|
||||
//booleanOper 不接管入参,原来每个被合并掉的克隆体都泄漏
|
||||
DELETE_PTR(pSolid);
|
||||
}
|
||||
}
|
||||
else
|
||||
@@ -3156,9 +3145,17 @@ 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];
|
||||
AecEqui::XPrimData *p = (AecEqui::XPrimData *)m_arSubPrimPtrs[nIndex];
|
||||
if (p != NULL)
|
||||
{
|
||||
p->releaseData();
|
||||
DELETE_PTR(p);
|
||||
}
|
||||
m_arSubPrimPtrs.RemoveAt(nIndex);
|
||||
}
|
||||
|
||||
m_arSubPrimPtrs.Append(ar);
|
||||
@@ -4031,9 +4028,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 +4042,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;
|
||||
}
|
||||
@@ -4264,6 +4265,20 @@ void AecDbEwEquipment::AddSubPrimObj(AecEqui::XPrimData* p)
|
||||
m_arSubPrimPtrs.Add(pData);
|
||||
}
|
||||
|
||||
void AecDbEwEquipment::FreeSubPrimData()
|
||||
{
|
||||
for (int i = 0; i < m_arSubPrimPtrs.GetSize(); i++)
|
||||
{
|
||||
AecEqui::XPrimData* pData = (AecEqui::XPrimData*)m_arSubPrimPtrs.GetAt(i);
|
||||
if (pData != NULL)
|
||||
{
|
||||
pData->releaseData();
|
||||
DELETE_PTR(pData);
|
||||
}
|
||||
}
|
||||
m_arSubPrimPtrs.RemoveAll();
|
||||
}
|
||||
|
||||
void AecDbEwEquipment::RemoveSubPrimObj(int nIndex)
|
||||
{
|
||||
AssertWriteEnabled();
|
||||
@@ -4273,6 +4288,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"));
|
||||
pSolid->releaseData();
|
||||
DELETE_PTR(pSolid);
|
||||
}
|
||||
}
|
||||
@@ -4288,6 +4304,7 @@ void AecDbEwEquipment::RemoveSubPrimObjByID(int nSubID)
|
||||
{
|
||||
m_arSubPrimPtrs.RemoveAt(i);
|
||||
m_mapSpecXData.RemoveAt(TypeConvert::i2s(pSolid->m_nID) + _T(":color"));
|
||||
pSolid->releaseData();
|
||||
DELETE_PTR(pSolid);
|
||||
break;
|
||||
}
|
||||
@@ -8517,8 +8534,8 @@ void AecDbEwEquipment::PrimPorjectToPlan(AecComplexCurve& cplCurve, AecEqui::XVi
|
||||
}
|
||||
|
||||
//3.释放内存
|
||||
FreeBuffer2(arPrimCplPtrs);
|
||||
FreeBuffer3(arFaceplanPtrs);
|
||||
FreeComplexCurveArray(arPrimCplPtrs);
|
||||
FreeFaceplanArray(arFaceplanPtrs);
|
||||
}
|
||||
|
||||
void AecDbEwEquipment::PrimBoxPorjectToPlan(AecComplexCurve& cplCurve, AecEqui::XView eview, const AcGeVector3d& vtNor, AecEqui::XPrimData* p3dSolid, Aec3dFaceplan* pPlan, BOOL bMakeCenterLine /*= FALSE*/, BOOL bOnlyGetFace /*= FALSE*/) const
|
||||
@@ -11233,7 +11250,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);
|
||||
|
||||
@@ -11337,7 +11358,7 @@ void AecDbEwEquipment::SplitCrvOnIntersect(AecComplexCurve* pCrvDn, AecComplexCu
|
||||
AecCoverBooleanOper::SortPoints(arPts, pDbCrvDn);
|
||||
pDbCrvDn->getSplitCurves(arPts, arSegPtrs);
|
||||
AppendSegment(elDn, cplexDn, arSegPtrs, dZ);
|
||||
FreeBuffer(arSegPtrs);
|
||||
FreeEntityArray(arSegPtrs);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -11351,7 +11372,7 @@ void AecDbEwEquipment::SplitCrvOnIntersect(AecComplexCurve* pCrvDn, AecComplexCu
|
||||
|
||||
*pCrvDn = cplexDn;
|
||||
|
||||
FreeBuffer(arUpCrvPtrs);
|
||||
FreeEntityArray(arUpCrvPtrs);
|
||||
}
|
||||
|
||||
AcDbCurve* AecDbEwEquipment::CurveElement2DbCurve(AecEqui::AecCurveElement el) const
|
||||
@@ -12556,10 +12577,20 @@ 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);
|
||||
//原来这里直接跳过,pRec 既不关闭也不删除,每次调用泄漏一个块表记录
|
||||
pRec->close();
|
||||
return false;
|
||||
}
|
||||
|
||||
Acad::ErrorStatus esAdd = pTbl->add(idRec, pRec);
|
||||
pTbl->close();
|
||||
if (esAdd != Acad::eOk)
|
||||
{
|
||||
pRec->close();
|
||||
return false;
|
||||
}
|
||||
|
||||
TCHAR szHd[17];
|
||||
idRec.handle().getIntoAsciiBuffer(szHd);
|
||||
@@ -12585,7 +12616,6 @@ DLLIMPEXP bool MakeBlockRefSet(AcDbVoidPtrArray& arEntPtrs,const AcDbObjectId& i
|
||||
pRef->setLayer(idLay);
|
||||
arEntPtrs.append(pRef);
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -12624,8 +12654,12 @@ bool AecDbEwEquipment::OldGetSectionDraw(AcGePlane &plan, const AcGeVector3d &vt
|
||||
{
|
||||
OrthoProjected3DSolid(pSolidT, plan, xform, arProPtrs);
|
||||
}
|
||||
//非 solid 的克隆体原来既不进结果也不释放
|
||||
DELETE_PTR(pSubCln);
|
||||
}
|
||||
}
|
||||
//GetDraw3dables 产出的整组克隆,原来从头到尾没释放
|
||||
FreeEntityArray(arSubPtrs);
|
||||
|
||||
CString sName;
|
||||
m_mapSpecXData.GetAt(KEY_NAME, sName);
|
||||
@@ -12688,6 +12722,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 +12774,7 @@ bool AecDbEwEquipment::GetSectionDraw(AcGePlane& plan,const AcGeVector3d& vtTo,A
|
||||
}
|
||||
else//不是阀门,其他设备
|
||||
{
|
||||
delete pFit;
|
||||
return OldGetSectionDraw(plan, vtTo, arRegionPtrs);
|
||||
}
|
||||
}
|
||||
@@ -12848,11 +12884,21 @@ bool AecDbEwEquipment::ByJson(const SHJson::WValue &v)
|
||||
it = v.FindMember(_T("__arSubPrimPtrs__"));
|
||||
if (it == v.MemberEnd()) return false;
|
||||
if (!it->value.IsArray()) return false;
|
||||
|
||||
//先释放旧几何,否则对已有对象再导入会叠加重复单元
|
||||
FreeSubPrimData();
|
||||
|
||||
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
|
||||
{
|
||||
//解析失败,原来既不进数组也不释放
|
||||
p->releaseData();
|
||||
DELETE_PTR(p);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
@@ -57,7 +57,7 @@ namespace
|
||||
{
|
||||
::Sleep(30);
|
||||
pXPData->m_nID = ::GetTickCount();
|
||||
pXPData->m_pData = new T;
|
||||
pXPData->m_pData = new unsigned char[sizeof(T)];
|
||||
::memcpy(pXPData->m_pData, pData, sizeof(T));
|
||||
pXPData->m_nSize = sizeof(T);
|
||||
}
|
||||
|
||||
@@ -6131,7 +6131,7 @@ namespace
|
||||
}
|
||||
break;
|
||||
default:
|
||||
pXPData->m_pData = new T;
|
||||
pXPData->m_pData = new unsigned char[sizeof(T)];
|
||||
::memcpy(pXPData->m_pData, pData, sizeof(T));
|
||||
pXPData->m_nSize = sizeof(T);
|
||||
break;
|
||||
|
||||
@@ -321,7 +321,7 @@ namespace
|
||||
}
|
||||
break;
|
||||
default:
|
||||
pXPData->m_pData = new T;
|
||||
pXPData->m_pData = new unsigned char[sizeof(T)];
|
||||
::memcpy(pXPData->m_pData, pData, sizeof(T));
|
||||
pXPData->m_nSize = sizeof(T);
|
||||
break;
|
||||
|
||||
@@ -275,7 +275,7 @@ namespace
|
||||
}
|
||||
break;
|
||||
default:
|
||||
pXPData->m_pData = new T;
|
||||
pXPData->m_pData = new unsigned char[sizeof(T)];
|
||||
::memcpy(pXPData->m_pData, pData, sizeof(T));
|
||||
pXPData->m_nSize = sizeof(T);
|
||||
break;
|
||||
|
||||
@@ -18667,7 +18667,7 @@ void PL_PARAM_NOZZ()
|
||||
data.m_nID = ::_time32(NULL);
|
||||
data.m_iClr = 1;
|
||||
|
||||
data.m_pData = new AecEqui::XNozz;
|
||||
data.m_pData = new unsigned char[sizeof(AecEqui::XNozz)];
|
||||
::memcpy(data.m_pData, pNozzData, sizeof(AecEqui::XNozz));
|
||||
data.m_nSize = sizeof(AecEqui::XNozz);
|
||||
data.m_nActiveInf = 0;
|
||||
|
||||
@@ -27,7 +27,7 @@ namespace
|
||||
}
|
||||
break;
|
||||
default:
|
||||
pXPData->m_pData = new T;
|
||||
pXPData->m_pData = new unsigned char[sizeof(T)];
|
||||
::memcpy(pXPData->m_pData, pData, sizeof(T));
|
||||
pXPData->m_nSize = sizeof(T);
|
||||
break;
|
||||
|
||||
@@ -50,7 +50,7 @@ namespace
|
||||
}
|
||||
break;
|
||||
default:
|
||||
pXPData->m_pData = new T;
|
||||
pXPData->m_pData = new unsigned char[sizeof(T)];
|
||||
::memcpy(pXPData->m_pData, pData, sizeof(T));
|
||||
pXPData->m_nSize = sizeof(T);
|
||||
break;
|
||||
|
||||
@@ -44,7 +44,7 @@ namespace
|
||||
}
|
||||
break;
|
||||
default:
|
||||
pXPData->m_pData = new T;
|
||||
pXPData->m_pData = new unsigned char[sizeof(T)];
|
||||
::memcpy(pXPData->m_pData, pData, sizeof(T));
|
||||
pXPData->m_nSize = sizeof(T);
|
||||
break;
|
||||
@@ -673,7 +673,7 @@ CSBZWDlg::CSBZWDlg(CWnd* pParent /*=NULL*/)
|
||||
|
||||
m_boxData.m_eType = AecEqui::kBox;
|
||||
m_boxData.m_nID = ::_time32(NULL);
|
||||
m_boxData.m_pData = new AecEqui::XBOX;
|
||||
m_boxData.m_pData = new unsigned char[sizeof(AecEqui::XBOX)];
|
||||
m_boxData.m_iClr = m_clr;
|
||||
|
||||
AecEqui::XBox box;
|
||||
@@ -716,7 +716,7 @@ CSBZWDlg::CSBZWDlg(double dX, double dY, double dZ, CWnd *pParent /*=NULL*/)
|
||||
|
||||
m_boxData.m_eType = AecEqui::kBox;
|
||||
m_boxData.m_nID = ::_time32(NULL);
|
||||
m_boxData.m_pData = new AecEqui::XBOX;
|
||||
m_boxData.m_pData = new unsigned char[sizeof(AecEqui::XBOX)];
|
||||
m_boxData.m_iClr = m_clr;
|
||||
|
||||
AecEqui::XBox box;
|
||||
@@ -932,7 +932,7 @@ Adesk::Int32 CSBZWDlg::AddNozz(DWORD dwSubiD, AcGeVector3d& vtDir, AcGePoint3d&
|
||||
data.m_nID = ::_time32(NULL);
|
||||
data.m_iClr = clr;
|
||||
|
||||
data.m_pData = new AecEqui::XNozz;
|
||||
data.m_pData = new unsigned char[sizeof(AecEqui::XNozz)];
|
||||
::memcpy(data.m_pData, pNozzData, sizeof(AecEqui::XNozz));
|
||||
data.m_nSize = sizeof(AecEqui::XNozz);
|
||||
data.m_nActiveInf = -1;
|
||||
|
||||
@@ -42,7 +42,7 @@ namespace MKValve
|
||||
}
|
||||
break;
|
||||
default:
|
||||
pXPData->m_pData = new T;
|
||||
pXPData->m_pData = new unsigned char[sizeof(T)];
|
||||
::memcpy(pXPData->m_pData, pData, sizeof(T));
|
||||
pXPData->m_nSize = sizeof(T);
|
||||
break;
|
||||
@@ -1951,7 +1951,7 @@ namespace MKHvacValve
|
||||
}
|
||||
break;
|
||||
default:
|
||||
pXPData->m_pData = new T;
|
||||
pXPData->m_pData = new unsigned char[sizeof(T)];
|
||||
::memcpy(pXPData->m_pData, pData, sizeof(T));
|
||||
pXPData->m_nSize = sizeof(T);
|
||||
break;
|
||||
|
||||
@@ -83,7 +83,7 @@ namespace FENGJI
|
||||
}
|
||||
break;
|
||||
default:
|
||||
pXPData->m_pData = new T;
|
||||
pXPData->m_pData = new unsigned char[sizeof(T)];
|
||||
::memcpy(pXPData->m_pData, pData, sizeof(T));
|
||||
pXPData->m_nSize = sizeof(T);
|
||||
break;
|
||||
|
||||
@@ -6540,7 +6540,7 @@ void PL_FZGZCmd()
|
||||
data.m_nID = ::_time32(NULL);
|
||||
data.m_iClr = 1;
|
||||
|
||||
data.m_pData = new AecEqui::XNozz;
|
||||
data.m_pData = new unsigned char[sizeof(AecEqui::XNozz)];
|
||||
::memcpy(data.m_pData, pNozzData, sizeof(AecEqui::XNozz));
|
||||
data.m_nSize = sizeof(AecEqui::XNozz);
|
||||
data.m_nActiveInf = 0;
|
||||
|
||||
@@ -360,6 +360,8 @@ public:
|
||||
void AddSubPrimObj(AecEqui::XPrimData* p);
|
||||
void RemoveSubPrimObj(int nIndex);
|
||||
void RemoveSubPrimObjByID(int nSubID);
|
||||
//释放全部几何单元(m_arSubPrimPtrs 里的 XPrimData 及其 m_pData)
|
||||
void FreeSubPrimData();
|
||||
|
||||
void AddTransform(const AcGeMatrix3d& xform);
|
||||
void AddTransform(const AcGeVector3d& vtMove);
|
||||
|
||||
@@ -2538,30 +2538,19 @@ namespace AecEqui
|
||||
}
|
||||
~XPrimData()
|
||||
{
|
||||
releaseData();
|
||||
for (size_t i(0); i < m_Combins.size(); ++i)
|
||||
DELETE_PTR(m_Combins[i]);
|
||||
}
|
||||
void releaseData()
|
||||
{
|
||||
if (!m_pData) return;
|
||||
switch (m_eType)
|
||||
{
|
||||
case AecEqui::kNewExtrude:
|
||||
case AecEqui::kNewRevolve :
|
||||
case AecEqui::kNewLoft:
|
||||
case AecEqui::kRevitSweep:
|
||||
case AecEqui::kNewSweep:
|
||||
case AecEqui::kRevitCombination:
|
||||
case AecEqui::kExtrude:
|
||||
case AecEqui::kRevolve:
|
||||
delete[] m_pData;
|
||||
//m_pData 一律用 new unsigned char[] 分配(dwgInFieldsForXPrim、byJson、
|
||||
//copyXPrimData 以及各命令模块的 setData),元素都是 POD,不含析构,
|
||||
//所以释放规则只有一条:delete[]。不要再按 m_eType 区分。
|
||||
if (m_pData == NULL) return;
|
||||
delete[] (unsigned char*)m_pData;
|
||||
m_pData = NULL;
|
||||
m_nSize = 0;
|
||||
break;
|
||||
default:
|
||||
delete m_pData;
|
||||
m_nSize = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//基本体数据
|
||||
short m_eType; //单元体类型
|
||||
|
||||
Reference in new issue
Block a user