[Finally DONE] conda: vtk9 / occt7.5 / python3.9 / boost1.74 migration

This subforum is specifically to discuss packaging issues on different platforms (windows, mac, linux), and using different packaging systems (conda, etc...)
tom
Posts: 165
Joined: Sun Mar 29, 2015 9:20 pm

Re: [C++ EXPERT NEEDED!!!!] conda: vtk9 / occt7.5 / python3.9 / boost1.74 migration

Post by tom »

@Iooo: When you are in lldb at the crash location, can you type in the "dis" command in order to see the assembly instructions being executed here? I have the suspicion that the compiler generates some fancy SSE instructions for the vector delete, but your processor does not support those. I had a similar issue with FC on my old MacBook Air (2011).
User avatar
looo
Veteran
Posts: 3941
Joined: Mon Nov 11, 2013 5:29 pm

Re: [C++ EXPERT NEEDED!!!!] conda: vtk9 / occt7.5 / python3.9 / boost1.74 migration

Post by looo »

not sure if I have done this right:

Code: Select all

lldb test_StdMeshers
(lldb) target create "test_StdMeshers"
Current executable set to 'test_StdMeshers' (x86_64).
(lldb) run
Process 12619 launched: '/Users/lo/miniconda3/conda-bld/debug_1633249932673/work/SMESH/test/tests/test_StdMeshers' (x86_64)
~SMDS_ElementChunk: 0x106600390
libSMDS.dylib was compiled with optimization - stepping may behave oddly; variables may not be available.
Process 12619 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
    frame #0: 0x00000001029fe844 libSMDS.dylib`SMDS_MeshElement::~SMDS_MeshElement(this=0x00000001068203f8) at SMDS_MeshElement.hxx:55 [opt]
Target 0: (test_StdMeshers) stopped.
(lldb) bt
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
  * frame #0: 0x00000001029fe844 libSMDS.dylib`SMDS_MeshElement::~SMDS_MeshElement(this=0x00000001068203f8) at SMDS_MeshElement.hxx:55 [opt]
    frame #1: 0x00000001029fe799 libSMDS.dylib`SMDS_ElementChunk::~SMDS_ElementChunk(this=<unavailable>) at SMDS_ElementFactory.cxx:546 [opt]
    frame #2: 0x00000001029fe869 libSMDS.dylib`SMDS_ElementChunk::~SMDS_ElementChunk(this=<unavailable>) at SMDS_ElementFactory.cxx:544 [opt]
    frame #3: 0x0000000102a00783 libSMDS.dylib`void boost::checked_delete<SMDS_ElementChunk const>(x=<unavailable>) at checked_delete.hpp:36 [opt]
    frame #4: 0x0000000102a00769 libSMDS.dylib`void boost::delete_clone<SMDS_ElementChunk>(r=<unavailable>) at clone_allocator.hpp:45 [opt]
    frame #5: 0x0000000102a00719 libSMDS.dylib`void boost::heap_clone_allocator::deallocate_clone<SMDS_ElementChunk>(r=<unavailable>) at clone_allocator.hpp:63 [opt]
    frame #6: 0x0000000102a00684 libSMDS.dylib`void boost::ptr_container_detail::reversible_ptr_container<boost::ptr_container_detail::sequence_config<SMDS_ElementChunk, std::__1::vector<void*, std::__1::allocator<void*> > >, boost::heap_clone_allocator>::remove<boost::void_ptr_iterator<std::__1::__wrap_iter<void**>, SMDS_ElementChunk> >(this=<unavailable>, i=<unavailable>) at reversible_ptr_container.hpp:237 [opt]
    frame #7: 0x0000000102a0052c libSMDS.dylib`void boost::ptr_container_detail::reversible_ptr_container<boost::ptr_container_detail::sequence_config<SMDS_ElementChunk, std::__1::vector<void*, std::__1::allocator<void*> > >, boost::heap_clone_allocator>::remove<boost::void_ptr_iterator<std::__1::__wrap_iter<void**>, SMDS_ElementChunk> >(this=<unavailable>, first=void_ptr_iterator<std::__1::__wrap_iter<void **>, SMDS_ElementChunk> @ 0x00007ffeefbfc298, last=void_ptr_iterator<std::__1::__wrap_iter<void **>, SMDS_ElementChunk> @ 0x00007ffeefbfc290) at reversible_ptr_container.hpp:244 [opt]
    frame #8: 0x0000000102a004c8 libSMDS.dylib`boost::ptr_container_detail::reversible_ptr_container<boost::ptr_container_detail::sequence_config<SMDS_ElementChunk, std::__1::vector<void*, std::__1::allocator<void*> > >, boost::heap_clone_allocator>::remove_all(this=<unavailable>) at reversible_ptr_container.hpp:205 [opt]
    frame #9: 0x0000000102a0047f libSMDS.dylib`boost::ptr_container_detail::reversible_ptr_container<boost::ptr_container_detail::sequence_config<SMDS_ElementChunk, std::__1::vector<void*, std::__1::allocator<void*> > >, boost::heap_clone_allocator>::~reversible_ptr_container(this=<unavailable>) at reversible_ptr_container.hpp:499 [opt]
    frame #10: 0x0000000102a00469 libSMDS.dylib`boost::ptr_sequence_adapter<SMDS_ElementChunk, std::__1::vector<void*, std::__1::allocator<void*> >, boost::heap_clone_allocator>::~ptr_sequence_adapter(this=<unavailable>) at ptr_sequence_adapter.hpp:135 [opt]
    frame #11: 0x0000000102a00459 libSMDS.dylib`boost::ptr_vector<SMDS_ElementChunk, boost::heap_clone_allocator, void>::~ptr_vector(this=<unavailable>) at ptr_vector.hpp:39 [opt]
    frame #12: 0x00000001029fc6c9 libSMDS.dylib`boost::ptr_vector<SMDS_ElementChunk, boost::heap_clone_allocator, void>::~ptr_vector(this=<unavailable>) at ptr_vector.hpp:39 [opt]
    frame #13: 0x00000001029fd40c libSMDS.dylib`void (anonymous namespace)::clearVector<boost::ptr_vector<SMDS_ElementChunk, boost::heap_clone_allocator, void> >(v=<unavailable>) at ObjectPool.hxx:34 [opt]
    frame #14: 0x00000001029fd3ab libSMDS.dylib`SMDS_ElementFactory::Clear(this=<unavailable>) at SMDS_ElementFactory.cxx:270 [opt]
    frame #15: 0x00000001029fe1e9 libSMDS.dylib`SMDS_NodeFactory::Clear(this=<unavailable>) at SMDS_ElementFactory.cxx:470 [opt]
    frame #16: 0x0000000102a1752e libSMDS.dylib`SMDS_Mesh::Clear(this=<unavailable>) at SMDS_Mesh.cxx:1554 [opt]
    frame #17: 0x0000000102460e26 libSMESHDS.dylib`SMESHDS_Mesh::ClearMesh(this=<unavailable>) at SMESHDS_Mesh.cxx:1033 [opt]
    frame #18: 0x000000010104413d libSMESH.dylib`SMESH_Mesh::~SMESH_Mesh(this=<unavailable>) at SMESH_Mesh.cxx:192 [opt]
    frame #19: 0x00000001010444d9 libSMESH.dylib`SMESH_Mesh::~SMESH_Mesh(this=<unavailable>) at SMESH_Mesh.cxx:178 [opt]
    frame #20: 0x00000001010444ee libSMESH.dylib`SMESH_Mesh::~SMESH_Mesh(this=<unavailable>) at SMESH_Mesh.cxx:178 [opt]
    frame #21: 0x0000000100025e64 test_StdMeshers`____C_A_T_C_H____T_E_S_T____0() at StdMeshers.t.cpp:41 [opt]
    frame #22: 0x00000001000179e7 test_StdMeshers`Catch::TestInvokerAsFunction::invoke(this=<unavailable>) const at catch.hpp:14321 [opt]
    frame #23: 0x00000001000122d8 test_StdMeshers`Catch::TestCase::invoke(this=<unavailable>) const at catch.hpp:14160 [opt]
    frame #24: 0x0000000100012233 test_StdMeshers`Catch::RunContext::invokeActiveTestCase(this=<unavailable>) at catch.hpp:13020 [opt]
    frame #25: 0x0000000100010b45 test_StdMeshers`Catch::RunContext::runCurrentTest(this=<unavailable>, redirectedCout=<unavailable>, redirectedCerr=<unavailable>) at catch.hpp:12993 [opt]
    frame #26: 0x0000000100010413 test_StdMeshers`Catch::RunContext::runTest(this=<unavailable>, testCase=<unavailable>) at catch.hpp:12754 [opt]
    frame #27: 0x0000000100014460 test_StdMeshers`Catch::(anonymous namespace)::TestGroup::execute(this=<unavailable>) at catch.hpp:13347 [opt]
    frame #28: 0x0000000100013ea6 test_StdMeshers`Catch::Session::runInternal(this=<unavailable>) at catch.hpp:13553 [opt]
    frame #29: 0x0000000100013d72 test_StdMeshers`Catch::Session::run(this=<unavailable>) at catch.hpp:13509 [opt]
    frame #30: 0x0000000100025b08 test_StdMeshers`int Catch::Session::run<char>(this=<unavailable>, argc=<unavailable>, argv=<unavailable>) at catch.hpp:13231 [opt]
    frame #31: 0x0000000100025a8f test_StdMeshers`main(argc=<unavailable>, argv=<unavailable>) at catch.hpp:17526 [opt]
    frame #32: 0x00007fff69b12015 libdyld.dylib`start + 1
    frame #33: 0x00007fff69b12015 libdyld.dylib`start + 1
(lldb) dis
libSMDS.dylib`SMDS_MeshElement::~SMDS_MeshElement:
    0x1029fe840 <+0>: pushq  %rbp
    0x1029fe841 <+1>: movq   %rsp, %rbp
->  0x1029fe844 <+4>: ud2
    0x1029fe846 <+6>: nopw   %cs:(%rax,%rax)
(lldb)
the cxxflags contain this option: -mssse3
tom
Posts: 165
Joined: Sun Mar 29, 2015 9:20 pm

Re: [C++ EXPERT NEEDED!!!!] conda: vtk9 / occt7.5 / python3.9 / boost1.74 migration

Post by tom »

My assumption was wrong. It is not an SSE instruction, which causes the EXC_BAD_INSTRUCTION. Instead it is the UD2 instruction (https://mudongliang.github.io/x86/html/ ... d_318.html). Currently I have no idea, why the compiler should generate such an instruction. Perhaps it is an inline assembler instruction within a macro like the BUG() macro in the Linux kernel (see https://stackoverflow.com/questions/111 ... nux-kernel).

While looking for the source code of the SMDS_MeshElement destructor I found that in my FC sources there is no SMDS_MeshElement destructor at all. I looked at free cad-code/src/3rdParty/salomesmesh/inc/SMDS_MeshElement.hxx. At line 55 as stated in your stack trace there is no destructor. Do you use other salomesmesh sources than this in free cad-code/src/3rdParty?
wmayer
Founder
Posts: 20243
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: [C++ EXPERT NEEDED!!!!] conda: vtk9 / occt7.5 / python3.9 / boost1.74 migration

Post by wmayer »

tom wrote: Mon Oct 04, 2021 7:50 pm Do you use other salomesmesh sources than this in free cad-code/src/3rdParty?
We are talking about these smesh sources: https://github.com/trelau/SMESH.git which uses the official sources as sub-module https://git.salome-platform.org/gitpub/ ... /smesh.git

You can view the sources with this URL: https://git.salome-platform.org/gitweb/ ... ;a=summary

The class SMDS_MeshElement has a compiler-generated destructor and the class SMDS_MeshObject defines a virtual destructor: https://git.salome-platform.org/gitweb/ ... db;hb=HEAD
User avatar
looo
Veteran
Posts: 3941
Joined: Mon Nov 11, 2013 5:29 pm

Re: [C++ EXPERT NEEDED!!!!] conda: vtk9 / occt7.5 / python3.9 / boost1.74 migration

Post by looo »

So myElements is an array of SMDS_MeshElement.

Code: Select all

SMDS_MeshElement*    myElements;    // array of elements
Calling delete on this array will call the destructor of SMDS_MeshElement which is a default destructor.

Code: Select all

delete [] myElements;
But the destructor of the derived class should be called. So we have to add a virtual destructor for SMDS_MeshElement.

Is this correct?
wmayer
Founder
Posts: 20243
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: [C++ EXPERT NEEDED!!!!] conda: vtk9 / occt7.5 / python3.9 / boost1.74 migration

Post by wmayer »

looo wrote: Tue Oct 05, 2021 10:40 am But the destructor of the derived class should be called. So we have to add a virtual destructor for SMDS_MeshElement.

Is this correct?
No. Once a method or destructor of a class is declared as virtual then for all derived classes this method or its destructor is automatically virtual, too -- even if the virtual keyword is missing in the (sub-)class declaration.

So, in this case myElements is filled with SMDS_MeshElement objects and when deleting the array it should call the destructor of SMDS_MeshElement. But because it also has a compiler-generated destructor you cannot see this easily.
wmayer
Founder
Posts: 20243
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: [C++ EXPERT NEEDED!!!!] conda: vtk9 / occt7.5 / python3.9 / boost1.74 migration

Post by wmayer »

But there is one strange thing with the smesh code. When I add an explicit constructor and destructor to SMDS_MeshCell

Code: Select all

SMDS_MeshCell() {
printf("SMDS_MeshCell\n");
}
~SMDS_MeshCell() {
printf("~SMDS_MeshCell\n");
}
then it prints SMDS_MeshCell when myElements is filled with SMDS_MeshCell. But when deleting the array then it doesn't call the destructor of SMDS_MeshCell.

When I also add a destructor to SMDS_MeshElement

Code: Select all

  virtual ~SMDS_MeshElement() {
      printf("~SMDS_MeshElement\n");
  }
then it prints ~SMDS_MeshElement.

How is that possible?

Here is a small test application that prints the expected output:

Code: Select all

MDS_MeshObject
SMDS_MeshElement
SMDS_MeshCell
SMDS_MeshObject
SMDS_MeshElement
SMDS_MeshCell
SMDS_MeshObject
SMDS_MeshElement
SMDS_MeshCell
Do SMDS_MeshCell
~SMDS_MeshCell
~SMDS_MeshElement
~SMDS_MeshObject
~SMDS_MeshCell
~SMDS_MeshElement
~SMDS_MeshObject
~SMDS_MeshCell
~SMDS_MeshElement
~SMDS_MeshObject

Code: Select all

#include <iostream>

class SMDS_MeshObject {
public:
  SMDS_MeshObject() {
    std::cout << "SMDS_MeshObject\n";
  }
  virtual ~SMDS_MeshObject() {
    std::cout << "~SMDS_MeshObject\n";
  }
  virtual void Do() {
    std::cout << "Do SMDS_MeshObject\n";
  }
};


class SMDS_MeshElement : public SMDS_MeshObject {
public:
  SMDS_MeshElement() {
    std::cout << "SMDS_MeshElement\n";
  }
  ~SMDS_MeshElement() {
    std::cout << "~SMDS_MeshElement\n";
  }
  void Do() {
    std::cout << "Do SMDS_MeshElement\n";
  }
};

class SMDS_MeshCell : public SMDS_MeshElement {
public:
  SMDS_MeshCell() {
    std::cout << "SMDS_MeshCell\n";
  }
  ~SMDS_MeshCell() {
    std::cout << "~SMDS_MeshCell\n";
  }
  void Do() {
    std::cout << "Do SMDS_MeshCell\n";
  }
};


int main()
{
   SMDS_MeshElement* o = new SMDS_MeshCell[3];
   o->Do();
   delete [] o;
}
wmayer
Founder
Posts: 20243
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: [C++ EXPERT NEEDED!!!!] conda: vtk9 / occt7.5 / python3.9 / boost1.74 migration

Post by wmayer »

In a second test when I replace SMDS_MeshElement* with std::vector<SMDS_MeshElement*> and make the required further changes then the destructor of SMDS_MeshCell will be called.
User avatar
looo
Veteran
Posts: 3941
Joined: Mon Nov 11, 2013 5:29 pm

Re: [C++ EXPERT NEEDED!!!!] conda: vtk9 / occt7.5 / python3.9 / boost1.74 migration

Post by looo »

wmayer wrote: Tue Oct 05, 2021 1:28 pm In a second test when I replace SMDS_MeshElement* with std::vector<SMDS_MeshElement*> and make the required further changes then the destructor of SMDS_MeshCell will be called.
can you send me the diff so I can try on the mac if it prevents the crash?
wmayer
Founder
Posts: 20243
Joined: Thu Feb 19, 2009 10:32 am
Contact:

Re: [C++ EXPERT NEEDED!!!!] conda: vtk9 / occt7.5 / python3.9 / boost1.74 migration

Post by wmayer »

I don't know how to get a diff with sub-modules. So, here are the changes you must apply:

In SMDS_ElementFactory.hxx replace

Code: Select all

  SMDS_MeshElement*    myElements;    // array of elements
with

Code: Select all

  std::vector<SMDS_MeshElement*>    myElements;    // array of elements
and

Code: Select all

  //! Return an element by an index [0,ChunkSize()]
  SMDS_MeshElement* Element(int index) { return & myElements[index]; }

  //! Return an element by an index [0,ChunkSize()]
  const SMDS_MeshElement* Element(int index) const { return & myElements[index]; }
with

Code: Select all

  //! Return an element by an index [0,ChunkSize()]
  SMDS_MeshElement* Element(int index) { return  myElements[index]; }

  //! Return an element by an index [0,ChunkSize()]
  const SMDS_MeshElement* Element(int index) const { return  myElements[index]; }
and

Code: Select all

int Index( const SMDS_MeshElement* e ) const { return (int)( e - myElements ); }
with (which is quite slow but for testing purposes OK)

Code: Select all

  int Index( const SMDS_MeshElement* e ) const {
      for (int i=0; i<myElements.size(); i++) {
          if (myElements[i] == e)
              return i;
      }
      return -1; // error
  }
In SMDS_ElementFactory.cxx replace

Code: Select all

  if ( myFactory->myIsNodal )
    myElements = new SMDS_MeshNode[ theChunkSize ];
  else
    myElements = new SMDS_MeshCell[ theChunkSize ];
with

Code: Select all

  myElements.resize(theChunkSize);
  if ( myFactory->myIsNodal ) {
      for (int i=0; i<theChunkSize; i++) {
          myElements[i] = new SMDS_MeshNode();
      }
  }
  else {
      for (int i=0; i<theChunkSize; i++) {
          myElements[i] = new SMDS_MeshCell();
      }
  }
and

Code: Select all

delete [] myElements;
with

Code: Select all

for (size_t i=0; i<myElements.size(); i++)
  delete myElements[i];
Post Reply