1

Closed

A crash associated with aborting through returning E_ABORT from statusCallBack

description

When statusCallback returns E_ABORT while control is in CIsochartMesh::PerformMerging in stage 2:
// 2. Begin from the charts with less faces try to merage them to the
// adjacent charts
    while(!heap.empty())
    {
     ....
UVAtlas seams to crash.

The model I'm working on is a sphere with ~2000 polygons,

I am calling UVAtlasCreate the conventional way, and operation completes fine without abort intervention. Here is the call to UVAtlasCreate:
  hr = UVAtlasCreate(inMesh->GetPositionBuffer(), nVerts,
    inMesh->GetIndexBuffer(), DXGI_FORMAT_R32_UINT, nFaces,
    _max_charts /*=0*/, stretch /*=0.05f*/, _side /*512*/, _side /*=512*/, _gutter/*=4*/,
    inMesh->GetAdjacencyBuffer(), nullptr /*falseEdgeAdjacency*/,
    nullptr/*IMTData.get()*/,
    _callback, UVATLAS_DEFAULT_CALLBACK_FREQUENCY,
    option/*=UVATLAS_GEODESIC_QUALITY*/, vb, ib,
    nullptr  /*facePartitioning*/,
    out_vert_remap,
    &outStretch, &outCharts);
And my statusCallback (for reference):
class UVAtlasCallback {
public:
  UVAtlasCallback(ProgressCommunication *progress_comm) : _progress_comm(progress_comm) {}
  HRESULT operator()(float fPercentDone) {
    if (_progress_comm->canceled) {
      return E_ABORT;
    }
    return S_OK;
  }
private:
  ProgressCommunication *_progress_comm;
};
Crash source in my case starts when
CIsochartMesh::MergeSmallCharts
makes call to
ReleaseAllNewCharts(children);
and returns the E_ABORT.

Subsequently all calling methods return the E_ABORT message until control reaches
Isochart::isochartpartition
and jumps to label:
LEnd:
which tries to call:
// 7. Free resources of isochart engine
pEngine->Free();
which internally calls for:
ReleaseInitialCharts();
which in turn loops on
m_initChartList
calling
delete pChart;
but pChart was already deleted back when we called:
CIsochartMesh::ReleaseAllNewCharts
Closed May 12, 2015 at 1:47 AM by walbourn
Fix submitted with check for pCharts being null.

comments

walbourn wrote May 8, 2015 at 11:27 PM

Thanks for the detailed report. Try this change:

mergecharts.cpp
void CIsochartMesh::ReleaseAllNewCharts(
    ISOCHARTMESH_ARRAY& children)
{
    for (size_t i=0; i<children.size(); i++)
    {
        auto* pChart = children[i];
        if ( !pChart->IsInitChart() )
        {
            delete pChart;
        }
    }
    children.clear();
}

walbourn wrote May 9, 2015 at 12:15 AM

Submitted the fix. If there are related additional crashes for the same case, please feel free to reopen this bug.

Thanks!

** Closed by walbourn 05/08/2015 4:15PM

has981 wrote May 10, 2015 at 4:22 PM

This would still crash when pChart is null, I've modified my local copy to add walbourn's fix but modified it by checking pChart first, like this:
void CIsochartMesh::ReleaseAllNewCharts(
    ISOCHARTMESH_ARRAY& children)
{
    for (size_t i=0; i<children.size(); i++)
    {
        auto* pChart = children[i];
        if ( pChart && !pChart->IsInitChart() )
        {
            delete pChart;
        }
    }
    children.clear();
}

walbourn wrote May 11, 2015 at 12:29 AM

That's what I ended up adding for the submit :)

walbourn wrote May 12, 2015 at 1:49 AM