Search code examples
c++c++11c++14opencascade

Assigning a TopoDS_Face object to its child object compiles with no errors but I have 3 valgrind errors


I have a class called Test which inherits the TopoDS_Face class. Already got some tips from This question but...

    // Test.h
    class Test : public TopoDS_Face
    {
      public:
         void operator = (const TopoDS_Face& base_)
         {
            TopoDS_Face::operator=(base_);
         }
    }

    // testmain.cpp 
    ...
    int main() {
      //extract faces from IGES face
      for (int i = 1; i <= nbs; i++) {
        TopoDS_Shape shape = myIgesReader.Shape(i);
        TopoDS_Face& face = static_cast<TopoDS_Face&>(TopoDS::Face(shape));
        Test *test;
        // tried each of these also and did not succeed
        // Test *test = dynamic_cast<Test*>(&face);
        // test = &face

        test->TopoDS_Face::operator=(face);
        ...
    }

}

The code in main extracts faces from an IGES file and assigns each face object to the test object created in main. The compilation goes on well but valgrind complains with the following error:

==21718== Use of uninitialised value of size 8
==21718==    at 0x9B0946C: Handle_Standard_Transient::Assign(Standard_Transient const*) (in /usr/lib64/libTKernel.so.10.0.0)
==21718==    by 0x408111: Handle_TopoDS_TShape::operator=(Handle_TopoDS_TShape const&) (in /home/ub/Projects/C++/test/test)
==21718==    by 0x409478: TopoDS_Shape::operator=(TopoDS_Shape const&) (in /home/ub/Projects/C++/test/test)
==21718==    by 0x4094CA: TopoDS_Face::operator=(TopoDS_Face const&) (in /home/ub/Projects/C++/test/test)
==21718==    by 0x407273: main (in /home/ub/Projects/C++/test/test)
==21718== 
==21718== Use of uninitialised value of size 8
==21718==    at 0x9B09431: Handle_Standard_Transient::EndScope() (in /usr/lib64/libTKernel.so.10.0.0)
==21718==    by 0x9B09475: Handle_Standard_Transient::Assign(Standard_Transient const*) (in /usr/lib64/libTKernel.so.10.0.0)
==21718==    by 0x408111: Handle_TopoDS_TShape::operator=(Handle_TopoDS_TShape const&) (in /home/ub/Projects/C++/test/test)
==21718==    by 0x409478: TopoDS_Shape::operator=(TopoDS_Shape const&) (in /home/ub/Projects/C++/test/test)
==21718==    by 0x4094CA: TopoDS_Face::operator=(TopoDS_Face const&) (in /home/ub/Projects/C++/test/test)
==21718==    by 0x407273: main (in /home/ub/Projects/C++/test/test)
==21718== 
==21718== Invalid read of size 4
==21718==    at 0x9B0943C: Handle_Standard_Transient::EndScope() (in /usr/lib64/libTKernel.so.10.0.0)
==21718==    by 0x9B09475: Handle_Standard_Transient::Assign(Standard_Transient const*) (in /usr/lib64/libTKernel.so.10.0.0)
==21718==    by 0x408111: Handle_TopoDS_TShape::operator=(Handle_TopoDS_TShape const&) (in /home/ub/Projects/C++/test/test)
==21718==    by 0x409478: TopoDS_Shape::operator=(TopoDS_Shape const&) (in /home/ub/Projects/C++/test/test)
==21718==    by 0x4094CA: TopoDS_Face::operator=(TopoDS_Face const&) (in /home/ub/Projects/C++/test/test)
==21718==    by 0x407273: main (in /home/ub/Projects/C++/test/test)
==21718==  Address 0x75eb394801c38350 is not stack'd, malloc'd or (recently) free'd
==21718== 
==21718== 
==21718== Process terminating with default action of signal 11 (SIGSEGV)
==21718==  General Protection Fault
==21718==    at 0x9B0943C: Handle_Standard_Transient::EndScope() (in /usr/lib64/libTKernel.so.10.0.0)
==21718==    by 0x9B09475: Handle_Standard_Transient::Assign(Standard_Transient const*) (in /usr/lib64/libTKernel.so.10.0.0)
==21718==    by 0x408111: Handle_TopoDS_TShape::operator=(Handle_TopoDS_TShape const&) (in /home/ub/Projects/C++/test/test)
==21718==    by 0x409478: TopoDS_Shape::operator=(TopoDS_Shape const&) (in /home/ub/Projects/C++/test/test)
==21718==    by 0x4094CA: TopoDS_Face::operator=(TopoDS_Face const&) (in /home/ub/Projects/C++/test/test)
==21718==    by 0x407273: main (in /home/ub/Projects/C++/test/test)
==21718== 

I need help with solving the program. Thanks in advance.


Solution

  • If you will take a look into TopoDS_Shape hierarchy definition you will notice that:

    • TopoDS_Shape is not an interface (there are no virtual methods nor virtual destructor).

    • TopoDS_Face, TopoDS_Shell and others provide 'dummy' inheritance from TopoDS_Shape without adding any fields or methods.

    • OCCT doesn't store strongly typed TopoDS_ shape object. OCCT collections (including sub-shapes of TopoDS_Shape, first of all!) store TopoDS_Shape by value, not reference. Methods like TopoDS::Face() basically does memory aliasing to return strongly typed object with runtime check based on enumeration returned by TopoDS_Shape::ShapeType() method.

    • Actually sharable reference is stored in form of Handle(TopoDS_TShape) property of TopoDS_Shape class. TopoDS_TShape is a real class defining main shape data (geometry), and it is indeed virtual class with real sub-classes.

    • TopoDS_TShape hierarchy (with subclasses like TopoDS_TShape, TopoDS_TShell and others) is internal and final - there is no interface for extending this hierarchy at application level. I would say, that within C++11, these classes are expected to be marked as final.

    Basing on this description, it should be clear that altering TopoDS_Shape / TopoDS_TShape hierarchy contradicts to OCCT design (for these specific classes) and cannot be done reliably at application level. Supposed alternative is storing additional information associated to shape using map (like NCollection_DataMap<TopoDS_Shape,TopTools_ShapeMapHasher,MyShapeProperties>) or by document structures (like XCAF document defining assembly structure with TDataStd_NamedData and other attributes).