Access violation in ShapeAnalysis_FreeBounds::ConnectWiresToWires

After slicing a shape with several planes I received EXCEPTION_ACCESS_VIOLATION calling ShapeAnalysis_FreeBounds::ConnectWiresToWires. Even if the wires cannot be connected the code should not raise an exception. The two problematic wires are attached in brep files to reproduce the error using the following code:

    //OSD::SetSignal(false);
    try
    {
        OCC_CATCH_SIGNALS

        BRep_Builder b;
        std::ifstream is;
        Handle(TopTools_HSequenceOfShape) hWires = new TopTools_HSequenceOfShape();

        TopoDS_Shape w1;
        is.open("w1.brep");
        BRepTools::Read(w1, is, b);
        is.close();
        hWires->Append(w1);

        TopoDS_Shape w2;
        is.open("w2.brep");
        BRepTools::Read(w2, is, b);
        is.close();
        hWires->Append(w2);


            Handle(TopTools_HSequenceOfShape) hSorted = new TopTools_HSequenceOfShape();
            ShapeAnalysis_FreeBounds::ConnectWiresToWires(hWires, PrecisionFactor*Precision::Confusion(), false, hSorted);

    }
    catch (const Standard_Failure& theErr)
    {
        //Message::SendFail() << "OCCT exception caught:\n" << theErr;
    }

The error occurs in all versions of opencascade (from 7.3 to 7.6.2) I tested using macOS and Windows.

Unfortunately, I cannot catch the exception either. The code I have commented out gives me compilation errors (Message::SendFail() - Function SendFail could not be resolved) but any other console output does not show up in the part of the code that handles the exception. What should I do to catch the exception?

Luis Diago's picture

Hello,

I continued looking for a solution but I have no idea about what the algorithm is doing?

First, I was able to catch the exception. As the macro OCC_CATCH_SIGNALS in its definition only catches exceptions of type STANDARD_TYPE(Standard_Failure) I had to replace it with the following code so that it could catch any other exceptions like STANDARD_TYPE(EXCEPTION_ACCESS_VIOLATION) or STANDARD_TYPE(OSD_SIGSEGV). I also included the possibility to catch the STANDARD_TYPE(OSD_Exception_CTRL_BREAK) exception in order to stop the program that was kept in an infinite loop.

                                    Standard_ErrorHandler _aHandler;
                                    if(setjmp(_aHandler.Label())) {
                                        _aHandler.Catches(STANDARD_TYPE(Standard_Failure));
                                        _aHandler.Catches(STANDARD_TYPE(OSD_SIGSEGV));
                                        _aHandler.Catches(STANDARD_TYPE(OSD_Exception_ACCESS_VIOLATION));
                                        _aHandler.Catches(STANDARD_TYPE(OSD_Exception_CTRL_BREAK));
                                        _aHandler.Error()->Reraise();
                                    }
                                    OSD::ControlBreak();

The infinite loop occurs in the ShapeAnalysis_FreeBounds::ConnectWiresToWires function in the following part of the code because the variable lwire is never -1:

//=======================================================================
//function : ConnectWiresToWires
//purpose  : 
//=======================================================================

 void ShapeAnalysis_FreeBounds::ConnectWiresToWires(Handle(TopTools_HSequenceOfShape)& iwires,
                            const Standard_Real toler,
                            const Standard_Boolean shared,
                            Handle(TopTools_HSequenceOfShape)& owires,
                            TopTools_DataMapOfShapeShape& vertices) 
{
  if (iwires.IsNull() || !iwires->Length()) return;
  Handle(TopTools_HArray1OfShape) arrwires = new TopTools_HArray1OfShape(1, iwires->Length());
  //amv

         ...
  aTreeFiller.Fill();
  Standard_Integer nsel;

  ShapeAnalysis_Edge sae; //szv#4:S4163:12Mar99 moved
  Standard_Boolean done = Standard_False;


  while (!done)
  {
    Standard_Boolean found = Standard_False, tail = Standard_False, direct = Standard_False;
    Standard_Integer lwire=0;
      ...

    if (found)
    {
      if (!direct)
        arrwires->ChangeValue(lwire).Reverse();

      TopoDS_Wire aCurW = TopoDS::Wire (arrwires->Value (lwire));
      Handle(ShapeExtend_WireData) acurwd = new 
        ShapeExtend_WireData ( TopoDS::Wire (arrwires->Value (lwire)), Standard_True, isUsedManifoldMode);
      if( !acurwd->NbEdges())
        continue;
      sewd->Add (acurwd, (tail ? 0 : 1));
    }
    else
    {
      // Recherche de la premier edge non traitee pour un autre wire.
      //Searching for first edge for next wire
      lwire = -1;
      for (/*Standard_Integer*/ i = 1 ; i <= arrwires->Length(); i++)
      {
        if (!aSel.ContWire(i))
        {
          lwire = i; //szv#4:S4163:12Mar99 optimized
          sewd->Add (TopoDS::Wire (arrwires->Value (lwire)));
          aSel.LoadList(lwire);

          if (sewd->NbEdges() > 0)
            break;
          sewd->Clear();
        }
      }

      if (lwire == -1)
        done = 1;
    }
  }

  for ( /*Standard_Integer*/ i = 1; i <= iwires->Length(); i++)
  {
    iwires->SetValue (i, arrwires->Value(i));
  }
}

Does anyone have any idea about what the algorithm is doing?