OCCT 6.9.1 persistence restored in OCCT 7.2.0 not working

Hello,

I have started to to upgrade my "EmCAD" code to OCC 7.2.0.

Having the need to read legacy files written with old Storage_ShapeSchema  format I have followed the related instructions on the official documentation

and here is a code snippet from my file "InputOutput.cpp":

   Handle(StdStorage_Data) data;

   Storage_Error error = StdStorage::Read(fileName, data);

 

This code crashes with the following error:    terminate called after throwing an instance of 'Storage_StreamFormatError'

I have attached the data file (model.brep) which I was trying to read with this code. This file can be read without problems using the old ShapeSchema and OCCT 6.9.1.

 

Following is the stack trace from gdb:

Thread 1 "emcad" received signal SIGABRT, Aborted.
0x00007fffee9d8428 in raise () from /lib/x86_64-linux-gnu/libc.so.6
(gdb) bt
#0  0x00007fffee9d8428 in raise () from /lib/x86_64-linux-gnu/libc.so.6
#1  0x00007fffee9da02a in abort () from /lib/x86_64-linux-gnu/libc.so.6
#2  0x00007fffef75a84d in __gnu_cxx::__verbose_terminate_handler() ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#3  0x00007fffef7586b6 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#4  0x00007fffef7576a9 in ?? () from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#5  0x00007fffef758005 in __gxx_personality_v0 ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#6  0x00007fffeef99f83 in ?? () from /lib/x86_64-linux-gnu/libgcc_s.so.1
#7  0x00007fffeef9a2eb in _Unwind_RaiseException ()
   from /lib/x86_64-linux-gnu/libgcc_s.so.1
#8  0x00007fffef75890c in __cxa_throw ()
   from /usr/lib/x86_64-linux-gnu/libstdc++.so.6
#9  0x00007ffff5c9b629 in FSD_File::EndReadObjectData() ()
   from /home/walter/local/OCC/lib/libTKernel.so.7
#10 0x00007ffff26b8a50 in ShapePersistent_TopoDS::HShape::Read(StdObjMgt_ReadData&) () from /home/walter/local/OCC/lib/libTKStd.so.7
#11 0x00007ffff23a340f in StdObjMgt_ReadData::ReadPersistentObject(int) ()
   from /home/walter/local/OCC/lib/libTKStdL.so.7
#12 0x00007ffff266f602 in StdStorage::Read(Storage_BaseDriver&, opencascade::handle<StdStorage_Data>&) () from /home/walter/local/OCC/lib/libTKStd.so.7
#13 0x00007ffff267069f in StdStorage::Read(TCollection_AsciiString const&, opencascade::handle<StdStorage_Data>&) ()
---Type <return> to continue, or q <return> to quit---
   from /home/walter/local/OCC/lib/libTKStd.so.7
#14 0x000000000058cf57 in openShape (
    fileName=0x1ade6a0 "/tmp/EmCAD-3zL5mp/Work/CMP_IN_1/model.brep", shape=...)
    at /home/walter/MwCAD/EmCAD/EmCAD-tet-OCC7_2_0/src/CAD/InputOutput.cpp:311

   ........

 

 

Regards

Walter Steffè

 

Attachments: 
Andrey BETENEV's picture

Hello Walter,

As exception name suggests, the reader apparently does not recognize this format.

Please give sample of the code that you use to read your files with OCCT 6.9.x

Andrey

Walter Steffè's picture

Hello Andrey, here are the first rows of the openShape function linked with with OCC 6.9 :

bool openShape( const char* fileName, TopoDS_Shape &shape)
{

    FSD_File *fileDriver=new FSD_File();    
    if ( FSD_File::IsGoodFileType( fileName ) != Storage_VSOk )  return false;

    TCollection_AsciiString aName( fileName );
    if ( fileDriver->Open( aName, Storage_VSRead ) != Storage_VSOk ) return false;

    Handle(ShapeSchema) schema = new ShapeSchema();
    Handle(Storage_Data) data  = schema->Read( *fileDriver );

   ......

Andrey BETENEV's picture

Hello Walter,

Your file seems to be read well by OCCT 7.2.0.

You can check this in DRAW (application installed with official distribution of OCCT 7.2.0): just start it and type two commands:
> pload ALL
> fsdread <your_file_path> a

Trying this I got valid shape, looking just the same as when read by OCCT 6.9.1.

Thus, please check your code. For possible reference you can find implementation of DRAW command fsdread in the file src/DDocStd/DDocStd_ShapeSchemaCommands.cxx

Andrey

Walter Steffè's picture

Hello Andrey, thanks for your help.

On my installation it crashes also inside of DRAW (see annexed screenshot).

So it depends on my installation.

I am on ubuntu 16.04 and I have built OCC 7.2.0 with CMAKE in the usual way.

I will build it again adding the debug option to see what is happening inside of OCC7.2 before crashing.

Walter

Attachments: 
Walter Steffè's picture

Having rebuilt OCC 7.2 with debug option I have tried to look again into the gdb trace but I am not able to catch the problem.

So I would like to share these data hoping that somebody else can see it.

I am also wondering if somebody else can confirm that DRAW crashes on a linux platform when reading the attached file "model.rep".

The relevant part of gdb trace is:

#9  0x00007ffff5ae7623 in FSD_File::EndReadObjectData (this=0x1d65080) at /home/walter/Software/OpenCascade/opencascade-7.2.0/src/FSD/FSD_File.cxx:1338
#10 0x00007ffff1cc8937 in StdObjMgt_ReadData::Object::~Object (this=0x7fffffff9bd0, __in_chrg=<optimized out>)
    at /home/walter/Software/OpenCascade/opencascade-7.2.0/src/StdObjMgt/StdObjMgt_ReadData.hxx:100
#11 0x00007ffff1cc90c0 in StdObject_Shape::read (this=0x1e6c268, theReadData=...)
    at /home/walter/Software/OpenCascade/opencascade-7.2.0/src/StdObject/StdObject_Shape.hxx:39
#12 0x00007ffff1d3d416 in ShapePersistent_TopoDS::HShape::Read (this=0x1e6c250, theReadData=...)
    at /home/walter/Software/OpenCascade/opencascade-7.2.0/src/ShapePersistent/ShapePersistent_TopoDS.cxx:42
#13 0x00007ffff192cda2 in StdObjMgt_ReadData::ReadPersistentObject (this=0x7fffffff9dd0, theRef=1)
    at /home/walter/Software/OpenCascade/opencascade-7.2.0/src/StdObjMgt/StdObjMgt_ReadData.cxx:33
#14 0x00007ffff1cd8313 in StdStorage::Read (theDriver=..., theData=...)
    at /home/walter/Software/OpenCascade/opencascade-7.2.0/src/StdStorage/StdStorage.cxx:162
 

In the following I am reporting  the status at some stack levels

# 9:

  myStream.get(c);
  while (c != ')') {
    if (IsEnd() || (c != ' ') || (c == '\n')) {
      throw Storage_StreamFormatError();
    }
    myStream.get(c);
  }

Here it si throwing the exception because the read char in null:

(gdb) p c
$5 = 0 '\000'

at # 10 it is inside on the destructor of "class StdObjMgt_ReadData::Object"

at # 14

  it is at line  162:    aReadData.ReadPersistentObject(i);

  Nearby lines are:

  for (Standard_Integer i = 1; i <= aHeaderData->NumberOfObjects(); i++)
  {
    try
    {
      OCC_CATCH_SIGNALS

      aReadData.ReadPersistentObject(i);  
      anError = Storage_VSOk;
    }

(gdb) p i

$6 = 1

(gdb) p aHeaderData->NumberOfObjects()
$7 = 624

It seem to me that the header was read in correct way. So the data file should have been properly opened.

For some reason it fails when reading the first object.

It is also not clear to me while it entered into a destructor and why a destructor need to read from the data file.

Walter

Walter Steffè's picture

I have done an experiment to get more information on the situation before the crash:

The following line:   "std::ios_base::iostate streamState=myStream.rdstate();"

was inserted into the following function which is defined inside of FSD_File.cxx

void FSD_File::EndReadObjectData() 
{

  char c;
  std::ios_base::iostate streamState=myStream.rdstate();
  myStream.get(c);
  while (c != ')') {
    if (IsEnd() || (c != ' ') || (c == '\n')) {
      throw Storage_StreamFormatError();
    }
    myStream.get(c);
  }

//  cout << "EndReadObjectData" << endl;
}

So I have discovered that when the code enters into that functions the stream status is not valid

(gdb) p streamState
$1 = std::_S_failbit 

and therefore c is not read inside of the function.

So the problem occurred in some other place before entering into the function void FSD_File::EndReadObjectData().  But I do not know where.

Walter

Andrey BETENEV's picture

Hello Walter,

I confirm that the problem is reproduced on Ubuntu (but not on Windows), and your finding that the stream is invalid at the point of error. The issue #29355 is now registered for that.

Regarding your question "It is also not clear to me while it entered into a destructor and why a destructor need to read from the data file." -- in this code destructor is used to eat closing parenthesis in the object data representation. This design can be arguable, but the logic here is clear.

Andrey