0

I am using the library HDF5 to save in binary.

I would like to have some sort of user defined "global" data types that I initialize at the beginning and then use it when needed.

For example I want to define a compound type for a "Vector" (which is just a struct whose components are two doubles: x,y).

I tried implementing this idea in the following way (that I basically took from this answer: https://stackoverflow.com/a/27088552/4746978 )

// inside Vector.h
struct Vector
{
     double x;
     double y;
}


// inside Hdf5types.h
#include "Vector.h"
class Hdf5types
{

private:
    static H5::CompType m_vectorType;

public:
    static const H5::CompType& getVectorType();

};


//inside Hdf5types.cpp
#include "Hdf5types.h"
H5::CompType Hdf5types::m_vectorType = Hdf5types::getVectorType();

const H5::CompType& Hdf5types::getVectorType()
{
    struct Initializer {
          Initializer() {
              m_vectorType = H5::CompType(sizeof(Vector));
              m_vectorType.insertMember("x", HOFFSET(Vector, x), H5::PredType::NATIVE_DOUBLE);
              m_vectorType.insertMember("y", HOFFSET(Vector, y), H5::PredType::NATIVE_DOUBLE);
          }
     };
     static Initializer ListInitializationGuard;
     return m_vectorType;
}

The code compiles but I get a problem at runtime as an exception is thrown:

Exception thrown: read access violation.

this-> was nullptr.

"this" refers to an object which is called "IdComponent" in the HDF5 library. I am not sure how to proceed since I do not have the time to dig into the library. Perhaps someone who knows HDF5 has a solution!

Community
  • 1
  • 1
Turms
  • 155
  • 1
  • 6

1 Answers1

1

You are assigning the value too early during startup of the program. So you're static assignment is calling HDF5 library functionality, which has not been instantiated yet. So SIGSEV.

What you could do would be this:

// inside Hdf5types.h
#include <H5Cpp.h>
#include "Vector.h"

class Hdf5types{

private:
  static H5::CompType* m_vectorType;

public:
  static const H5::CompType& getVectorType();

  Hdf5types();

};

#include "hdf5types.h"

H5::CompType* Hdf5types::m_vectorType = nullptr; 

Hdf5types::Hdf5types() {}

const H5::CompType& Hdf5types::getVectorType() {
  if (m_vectorType == nullptr) {
    struct Initializer {
      Initializer() {
        m_vectorType = new H5::CompType(sizeof(Vector));
        m_vectorType->insertMember("x", HOFFSET(Vector, x), H5::PredType::NATIVE_DOUBLE);
        m_vectorType->insertMember("y", HOFFSET(Vector, y), H5::PredType::NATIVE_DOUBLE);
      }
    };
    static Initializer ListInitializationGuard;
  }
  return *m_vectorType;
}

This would lazily initialise m_vectorType.

Kaveh Vahedipour
  • 3,412
  • 1
  • 14
  • 22
  • 1
    Thank you. That solved my problem! I guess I'll have to free that allocated memory right? I am not sure if doing it in the destructor will work, cause I am not creating any Hdf5 object. What do you think? – Turms Sep 13 '17 at 06:15
  • valgrind is not comlaining that the object is not freed. But you most definitely should add a destructor. – Kaveh Vahedipour Sep 13 '17 at 09:54