I am saving a compound data type made up of three variable length strings as an extendable dataset. Everything work well using HDF 1.8.1, but there is a 13.7K memory leak each time the dataset is written using HDF 1.12.1 or later. I’m assuming I need to add a call to some function to clean up the memory, but haven’t been able to find it.
This is the code I used for my testing. Any help is appreciated.
#include
#include
#include “H5Cpp.h”
#include “H5Ipublic.h”
using std::string;
typedef struct Hdf5MetaDataInfoV1
{
public:
const char* szSource;
const char* szLink;
const char* szDestination;
Hdf5MetaDataInfoV1()
: szSource(NULL), szLink(NULL), szDestination(NULL)
{
}
Hdf5MetaDataInfoV1(const Hdf5MetaDataInfoV1& info)
: szSource(NULL), szLink(NULL), szDestination(NULL)
{
this->Init(info.szSource, info.szLink, info.szDestination);
}
Hdf5MetaDataInfoV1(const char* source, const char* link, const char* dest)
: szSource(NULL), szLink(NULL), szDestination(NULL)
{
this->Init(source, link, dest);
}
Hdf5MetaDataInfoV1(const string& source, const string& link, const string& dest)
: szSource(NULL), szLink(NULL), szDestination(NULL)
{
this->Init(source, link, dest);
}
~Hdf5MetaDataInfoV1()
{
this->FreeMemory();
}
void operator=(const Hdf5MetaDataInfoV1& info)
{
this->Init(info.szSource, info.szLink, info.szDestination);
}
static H5::DataType* CreateStringType()
{
if (Hdf5MetaDataInfoV1::asciiType == NULL)
{
Hdf5MetaDataInfoV1::asciiType = new H5::StrType(H5::PredType::C_S1, H5T_VARIABLE);
}
return Hdf5MetaDataInfoV1::asciiType;
}
static H5::DataType* CreateMemoryType()
{
if (Hdf5MetaDataInfoV1::memoryType == NULL)
{
const H5::DataType* asciiType = CreateStringType();
H5::CompType type(sizeof(Hdf5MetaDataInfoV1));
type.insertMember("Source", HOFFSET(Hdf5MetaDataInfoV1, szSource), *asciiType);
type.insertMember("Link", HOFFSET(Hdf5MetaDataInfoV1, szLink), *asciiType);
type.insertMember("Destination", HOFFSET(Hdf5MetaDataInfoV1, szDestination), *asciiType);
Hdf5MetaDataInfoV1::memoryType = new H5::CompType(type);
}
return Hdf5MetaDataInfoV1::memoryType;
}
static H5::DataType* CreateFileType()
{
if (Hdf5MetaDataInfoV1::fileType == NULL)
{
const H5::DataType* asciiType = CreateStringType();
size_t offset = 0;
H5::CompType type(3 * asciiType->getSize());
type.insertMember("Source", offset, *asciiType);
offset += asciiType->getSize();
type.insertMember("Link", offset, *asciiType);
offset += asciiType->getSize();
type.insertMember("Destination", offset, *asciiType);
Hdf5MetaDataInfoV1::fileType = new H5::CompType(type);
}
return Hdf5MetaDataInfoV1::fileType;
}
static void ResetDataTypes()
{
if (Hdf5MetaDataInfoV1::asciiType != NULL)
{
Hdf5MetaDataInfoV1::asciiType->close();
delete Hdf5MetaDataInfoV1::asciiType;
Hdf5MetaDataInfoV1::asciiType = NULL;
}
if (Hdf5MetaDataInfoV1::memoryType != NULL)
{
Hdf5MetaDataInfoV1::memoryType->close();
delete Hdf5MetaDataInfoV1::memoryType;
Hdf5MetaDataInfoV1::memoryType = NULL;
}
if (Hdf5MetaDataInfoV1::fileType != NULL)
{
Hdf5MetaDataInfoV1::fileType->close();
delete Hdf5MetaDataInfoV1::fileType;
Hdf5MetaDataInfoV1::fileType = NULL;
}
}
private:
static H5::DataType* asciiType;
static H5::DataType* memoryType;
static H5::DataType* fileType;
void Init(const string& source, const string& link, const string& dest)
{
this->Init(source.c_str(), link.c_str(), dest.c_str());
}
void Init(const char* source, const char* link, const char* dest)
{
// Free the old data
this->FreeMemory();
// Copy the new data
if (source != NULL)
{
this->szSource = _strdup(source);
}
if (link != NULL)
{
this->szLink = _strdup(link);
}
if (dest != NULL)
{
this->szDestination = _strdup(dest);
}
}
void FreeMemory()
{
if (this->szSource != NULL)
{
free(const_cast<char*>(this->szSource));
this->szSource = NULL;
}
if (this->szLink != NULL)
{
free(const_cast<char*>(this->szLink));
this->szLink = NULL;
}
if (this->szDestination != NULL)
{
free(const_cast<char*>(this->szDestination));
this->szDestination = NULL;
}
}
} Hdf5MetaDataInfo;
H5::DataType* Hdf5MetaDataInfoV1::asciiType = NULL;
H5::DataType* Hdf5MetaDataInfoV1::memoryType = NULL;
H5::DataType* Hdf5MetaDataInfoV1::fileType = NULL;
void WriteFile(const char* fileName)
{
// Open the file
H5::FileAccPropList* accessPropList = new H5::FileAccPropList();
accessPropList->setFcloseDegree(H5F_CLOSE_SEMI);
H5::H5File* file = new H5::H5File(fileName, H5F_ACC_TRUNC, H5::FileCreatPropList::DEFAULT, *accessPropList);
// Make some data
Hdf5MetaDataInfo* fileData = new Hdf5MetaDataInfo[2];
fileData[0] = Hdf5MetaDataInfo("Root", "Attributes", "/System/Attributes");
fileData[1] = Hdf5MetaDataInfo("Root", "Measurement", "Some GUID");
// Store the data
H5::DataType* memoryType = Hdf5MetaDataInfo::CreateMemoryType();
H5::DataType* fileType = Hdf5MetaDataInfo::CreateFileType();
int rank = 1;
hsize_t* dims = new hsize_t[rank];
dims[0] = 2;
hsize_t* maxDims = new hsize_t[rank];
maxDims[0] = H5S_UNLIMITED;
H5::DataSpace space(rank, dims, maxDims);
H5::DSetCreatPropList createPropList;
createPropList.setChunk(rank, dims);
H5::DataSet dataSet = file->createDataSet("/Data", *fileType, space, createPropList);
// Write some data
dataSet.extend(dims);
dataSet.write(fileData, *memoryType);
// Cleanup the data
delete[] dims;
delete[] maxDims;
delete[] fileData;
space.close();
createPropList.close();
dataSet.close();
Hdf5MetaDataInfo::ResetDataTypes();
// Close and delete the access property list
if (accessPropList != NULL)
{
accessPropList->close();
delete accessPropList;
}
// Close and delete the file
if (file != NULL)
{
// Make sure all data is written
file->flush(H5F_SCOPE_GLOBAL);
// Close and delete the file
file->close();
delete file;
}
}
void LocalTest(const char* fileName)
{
int breakPoint = 0;
WriteFile(fileName);
// Loop for memory profiling
breakPoint = 1;
for (int idx = 0; idx < 1; idx++)
{
WriteFile(fileName);
}
breakPoint = 2;
}
int main()
{
const char* fileName = “C:\tmp\WriteTest.h5”;
int breakPoint = 0;
LocalTest(fileName);
}