Memory leak moving from 1.8.1 to 1.12.1 and later


#1

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);

}