修复相机 HLR 结果处理中的三处正确性缺陷

B1 mergeEnvelope:命中 isNull() 的 3DSOLID 时 pSolidAll 已赋值但未从 arptrs 摘除,
后续 deleteArrayVoidPtrs 会把它删掉,返回野指针。改为记下标、循环结束后统一 removeAt。

B2 process_result:outputWithoutID.append(entAr) 误写在 for 循环体内,每轮把累积数组
整体再追加一次,同一指针在 outputWithoutID 中出现多次,AddToModelSpace 第二次失败后
DELETE_PTR 会删掉已入库的实体。append 移到循环外,并先 entAr.removeAll()。

B3 process_result:erase 之后把 it 重置成 begin(),for 的 ++it 会跳过新的首元素,
多个构筑物时漏处理。改为 while + 先取 next 迭代器。

同时更新 HRL-MODEL-refactor.md:去掉未实施的内存账本方案,验证方法改为行为观察。
This commit is contained in:
company-desktop committed 2026-10-26 21:12:27 +08:00
1 parent ce886ff952
commit 39dbab85bf
2 files changed
+54 -21

No files matched your search

+32 -11
View File
@@ -750,16 +750,20 @@ namespace
if (arptrs.isEmpty()) return NULL;
// 找到第一个 3dsolid
// 找到第一个可用的 3dsolid。
// 这里只记下标、循环结束后再 removeAt:如果命中一个 isNull() 的 solid,
// pSolidAll 已经非空但没被摘掉,后面的 deleteArrayVoidPtrs(arptrs) 会把
// 它一起删掉,返回的就是野指针。
AcDb3dSolid *pSolidAll(NULL);
int nSolidIndex(-1);
for (int i(0); i < arptrs.length(); ++i)
{
AcDbEntity *pEnt((AcDbEntity *)arptrs[i]);
if (!pEnt) continue;
pSolidAll = AcDb3dSolid::cast(pEnt);
if (!pSolidAll) continue;
if (pSolidAll->isNull())
AcDb3dSolid *pSolid(AcDb3dSolid::cast(pEnt));
if (!pSolid) continue;
if (pSolid->isNull())
{
#ifndef NDEBUG
acutPrintf(_T("\nThe 3DSOLID does not have a ShapeManager object. "));
@@ -767,16 +771,19 @@ namespace
continue;
}
arptrs.removeAt(i);
pSolidAll = pSolid;
nSolidIndex = i;
break;
}
if (!pSolidAll)
if (nSolidIndex < 0)
{
deleteArrayVoidPtrs<AcDbEntity>(arptrs);
return NULL;
}
arptrs.removeAt(nSolidIndex);
if (arptrs.isEmpty()) return pSolidAll;
std::map<void *, AcDbHandle>::const_iterator debugIt(debugMM.end());
@@ -1003,6 +1010,7 @@ namespace
continue;
}
entAr.removeAll();
for (int i(0); i != arResult.length(); ++i)
{
AcDbEntity *pEnt = (AcDbEntity *)arResult[i]->clone();
@@ -1011,9 +1019,13 @@ namespace
pEnt->setLinetype(pSrc->linetypeId());
pEnt->setColorIndex(pSrc->colorIndex());
entAr.append(pEnt);
outputWithoutID.append(entAr);
}
// 必须放在循环外:entAr 不清空,放在循环里等于每轮把累积数组整体再追加一次,
// 同一指针会在 outputWithoutID 里出现多次,AddToModelSpace 第二次必然失败,
// 随后 DELETE_PTR 会删掉已经入库的实体。
if (!entAr.isEmpty())
outputWithoutID.append(entAr);
}
}
}
@@ -1157,16 +1169,25 @@ namespace
}
// 收集构筑物产生的结果(一般是不对构筑物进行融合的情况下)
// 注意:erase 之后不能把 it 重置成 begin(),否则 for 的 ++it 会跳过新的首元素。
IDMapEntities::iterator it(outputWithID.begin());
for (; it != outputWithID.end(); ++it)
while (it != outputWithID.end())
{
if (!isEnvelope(it->first)) continue;
if (!isEnvelope(it->first))
{
++it;
continue;
}
// 是构筑物结果,复制出来,并且删掉outputWithID里面的内容
for (int i(0); i < it->second.length(); ++i)
arEnvelope.append((AcDbEntity*)(it->second[i]->clone()));
deleteContainerOfArx<AcDbEntity>(it->second);
IDMapEntities::iterator itNext(it);
++itNext;
outputWithID.erase(it);
it = outputWithID.begin();
it = itNext;
}
// 处理构筑物