I have a serial communication library I am creating, and it is a managed assembly, which comes with it's own rules (I do not fully understand them, I just change code when VS complains), and I have a memory leak that I cannot figure out.
This is the leak warning that I get (line 11 is the InfoContainer constructor in SerialComm::SerialComm()):
Detected memory leaks!
Dumping objects ->
SerialComm.cpp(11) : {144} normal block at 0x011468B8, 56 bytes long.
Data: < > 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
Object dump complete.
This is the .h file for the lib:
#include <windows.h>
#include <stdlib.h>
#include <atlstr.h>
public class InfoContainer {
public:
~InfoContainer();
HANDLE handle;
bool connected;
COMSTAT status;
DWORD errors;
DCB connection_params;
CStringA port_name;
};
public ref class SerialComm {
public:
InfoContainer* info=0;
SerialComm();
~SerialComm();
bool OpenConnection(String^ Portname);
int CloseConnection();
bool WriteData(String^ toSend);
String^ ReadData(int bytesToRead);
};
and these are the relevant .cpp sections:
SerialComm::SerialComm() {
info = new (_NORMAL_BLOCK, __FILE__, __LINE__) InfoContainer();
info->handle = 0;
}
SerialComm::~SerialComm() {
CloseConnection();
delete info;
}
bool SerialComm::OpenConnection(String ^ Portname) {
info->port_name = Portname;
//visual studio's valgrindish tool
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);
_CrtSetReportMode(_CRT_ERROR, _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_ERROR, _CRTDBG_FILE_STDOUT);
_CrtSetReportMode(_CRT_ASSERT, _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_ASSERT, _CRTDBG_FILE_STDOUT);
_CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
_CrtDumpMemoryLeaks();
info->handle = CreateFileA(
info->port_name,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
0,
NULL
);
if (info->handle == INVALID_HANDLE_VALUE) {
ATLTRACE("Error: %d", GetLastError());
printf("Error: %d\n", GetLastError());
return false;
}
//
//rest of connection code here
//
}
int SerialComm::CloseConnection() {
return CloseHandle(info->handle);
}
InfoContainer::~InfoContainer() {
delete handle;
}
The reason I have to use an InfoContainer class and InfoContainer pointer in the main class is that some information I need to store is considered unmanaged code and so I cannot have it directly in the main class.
Thanks in advance!
The problem is _CrtDumpMemoryLeaks()
is called before all objects are deleted.
You need a finalizer. Following is the "golden pattern" when you write a class in C++/CLI:
virtual ~SerialComm()
{
this->!SerialComm();
}
!SerialComm()
{
}
Don't forget to add virtual to your destructor. The reason why virtual destructor is needed should be explained in any good C++ textbooks.