fix: 修复 AecDbEwEquipment 的内存泄漏(夹点数组、几何单元、剖切与投影克隆)

This commit is contained in:
company-desktop-computer committed 2026-10-23 09:57:20 +08:00
1 parent 55391b8dc8
commit 03bbe08b76
2 files changed
+164 -80

No files matched your search

@@ -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;