Loading simple RTF containing an image does not release memory on subsequent loads

roy nelson 0 Reputation points
2025-08-05T09:42:18.5566667+00:00

Consider this code it uses the MSFTEdit Richedit 50 control, every time you click the caption it will load the oom.rtf which contains an image, it displays the private bytes used by the process, (you can Task manager or Process explorer to the see the memory increase). There appear to be no way to stem the leak.

#include <windows.h>
#include <richedit.h>
#include <psapi.h>
static const TCHAR RTFFilename[] = TEXT("oom.rtf");
HWND RichEditHandle, MainWindowHandle;
DWORD CALLBACK MyRead(DWORD dwCookie, LPBYTE pbBuffer, LONG cb, LONG *pcb)
{
	HFILE	hf = (HFILE) dwCookie;
	if(hf == HFILE_ERROR)
		return (DWORD) E_FAIL;
	*pcb = _lread(hf, pbBuffer, cb);
	return (DWORD) (*pcb >= 0 ? NOERROR : (*pcb = 0, E_FAIL));
}
SIZE_T GetCurrentProcessMemoryInfo()
{
    PROCESS_MEMORY_COUNTERS_EX pmc;
	pmc.cb = sizeof(pmc);
	GetProcessMemoryInfo(GetCurrentProcess(), (PPROCESS_MEMORY_COUNTERS)&pmc,sizeof(pmc));
	return (pmc.PrivateUsage / 1024);
}
void ReadRTFFile(HWND hwndRE,  LPCSTR szFile)
{
	EDITSTREAM es;
    DWORD dwFormat;
	es.dwCookie = (DWORD) _lopen(szFile, OF_READ);
	if(es.dwCookie == (DWORD) HFILE_ERROR) return;
    dwFormat = SF_RTF;
	es.dwError = 0;
	es.pfnCallback = MyRead;
	SendMessage(hwndRE,EM_STREAMIN,dwFormat, (LPARAM) &es);
	_lclose((HFILE) es.dwCookie);
	SendMessage(hwndRE, EM_SETMODIFY, (WPARAM) FALSE, 0);
	InvalidateRect(hwndRE, NULL, TRUE);
	UpdateWindow(hwndRE);
}
void ShowMemoryUser(HWND WindowH)
{
	TCHAR szT[256];
    wsprintf(szT, TEXT("Loaded... %s memory used: %dkb"), RTFFilename,GetCurrentProcessMemoryInfo());
	SetWindowText(WindowH, szT);
}
void ShowLoading(HWND WindowH)
{
	TCHAR szT[256];
    wsprintf(szT, TEXT("Loading... %s memory used: %dkb"),RTFFilename, GetCurrentProcessMemoryInfo());
	SetWindowText(WindowH, szT);
}
#ifdef MSFTEDIT_CLASS
#undef MSFTEDIT_CLASS
#define MSFTEDIT_CLASS		"RICHEDIT50W"
#endif
LRESULT CALLBACK WndProc(HWND hwnd, UINT msg, WPARAM wp, LPARAM lp) {
    switch (msg) {
    case WM_CREATE: {
        LoadLibrary(TEXT("Msftedit.dll")); // Ensure the RichEdit DLL is loaded
        RichEditHandle = CreateWindowEx(0, MSFTEDIT_CLASS, TEXT(""),
            WS_CHILD | WS_VISIBLE | WS_BORDER | ES_MULTILINE | ES_AUTOVSCROLL,
            10, 10, 750, 550, hwnd, NULL, GetModuleHandle(NULL), NULL);
        ReadRTFFile(RichEditHandle,RTFFilename);
    }
       break;
    case WM_NCLBUTTONDOWN:
    {
       if (wp == HTCAPTION)
       {
        ShowLoading(MainWindowHandle);
       	ReadRTFFile(RichEditHandle, RTFFilename);
       	ShowMemoryUser(MainWindowHandle);
       } else
        return DefWindowProc(hwnd, msg, wp, lp);
    }
    break;
    case WM_DESTROY:
        PostQuitMessage(0);
        break;
    default:
        return DefWindowProc(hwnd, msg, wp, lp);
    }
    return 0;
}
int PASCAL
WinMain(HINSTANCE hinstCurr, HINSTANCE hinstPrev, LPSTR szCmdLine, int nCmdShow)
{
	WNDCLASS wc = { 0 };
	wc.lpfnWndProc = WndProc;
	wc.hInstance = hinstCurr;
	wc.lpszClassName = TEXT("MyLeaktestWindowClass");
	RegisterClass(&wc);
	MainWindowHandle = CreateWindow(wc.lpszClassName, TEXT("Click here.."),
		WS_OVERLAPPEDWINDOW, CW_USEDEFAULT, CW_USEDEFAULT,
		800, 600, NULL, NULL, hinstCurr, NULL);
	ShowWindow(MainWindowHandle, nCmdShow);
	UpdateWindow(MainWindowHandle);
    ShowMemoryUser(MainWindowHandle);
	MSG msg;
	while (GetMessage(&msg, NULL, 0, 0)) {
		TranslateMessage(&msg);
		DispatchMessage(&msg);
	}
	return 0;
}
Windows development | Windows API - Win32
0 comments No comments
{count} votes

Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.