Not sure why but im using Deleaker plugin to detect memory leaks.
in my code in debug build its saying i have amemory leak at GetDC
Then in release build it is saying i have a leak at CreateCompatibleDC
are these real leaks or false?
my delete objects are called when my class closes.
HDC hdc = GetDC(_hWnd);
_hdcMem = CreateCompatibleDC(hdc);
HBITMAP hbmOld = (HBITMAP)SelectObject(_hdcMem, _hBitmap);
while (_execute.load(std::memory_order_acquire))
{
func();
BitBlt(hdc, 0, 0, _Width, _Height, _hdcMem, 0, 0, SRCCOPY);
}
SelectObject(_hdcMem, hbmOld);
DeleteDC(_hdcMem);
DeleteObject(hbmOld);
DeleteObject(_hBitmap);
DeleteDC(hdc);
After GetDC, you must call ReleaseDC—not DeleteDC. DeleteDC is only used with CreateCompatibleDC. This is all spelled out in the documentation in case you forget.
Also, you are incorrectly cleaning up your device context. The reason you save the handles to the old objects is so that you can reselect them into the DC. You cannot delete them! Objects that are selected into a device context cannot be deleted—they are in use. (If you were checking the return values of these API functions, you would know that, because they would have returned an error.)
The code should look like this:
HDC hdc = GetDC(_hWnd);
_hdcMem = CreateCompatibleDC(hdc);
HBITMAP hbmOld = (HBITMAP)SelectObject(_hdcMem, _hBitmap);
while (_execute.load(std::memory_order_acquire))
{
func();
BitBlt(hdc, 0, 0, _Width, _Height, _hdcMem, 0, 0, SRCCOPY);
}
SelectObject(_hdcMem, hbmOld);
DeleteObject(_hBitmap);
DeleteDC(_hdcMem);
ReleaseDC(_hWnd, hdc);
It is unclear to me why you are using global variables for _hdcMem and _hBitmap when their scope is limited to this single bit of code. You create them at the top, and destroy them at the bottom, so they are useless outside of this code. You should limit their scope to just this section of the code, too. Being able to reason about the lifetime of objects/variables is key to stomping out memory leaks.
Note that using a library that wraps these native resources up in an RAII fashion (constructor acquires; destructor releases) would be a wonderful idea. It not only frees you from having to remember the details of how to clean up each time, but it also ensures that your code is exception-safe. If func() were to throw here, you would certainly have a memory leak. That is something a really good static analyzer would tell you as well.
You must use ReleaseDC() to free the HDC returned by GetDC().
Do not delete the hbmOld that SelectObject() returned. Just select it back into the HDC and let ReleaseDC() handle its deletion.
Related
This is my class constructor:
ActionButton::ActionButton(CallbackFunction function, void* param, HWND parent, int x, int y, int heigth, int width) :
m_function(function), m_parameters(param), m_window(NULL)
{
HWND m_window = CreateWindowEx(0, L"Action button", NULL, WS_CHILD | WS_VISIBLE,
x, y, width, heigth, parent, NULL, NULL, NULL);
DWORD dw = GetLastError();
SetWindowLongPtr(m_window, GWLP_USERDATA, (LONG_PTR)this);
ShowWindow(m_window, SW_NORMAL);
}
I used debuger and found that it executes CreateWindowEx() but after pressing F11 program jumped off the constructor (and I'm using only one thread). Is something wrong with my code?
After CreateWindowEx there is executing window procedure with parameters e.g WM_CREATE, so step after CreateWindowEx is not in constructor, after executing a few window procedure callbacks it goes back into constructor.
While executing CreateWindow[Ex] the system calls the window procedure associated with the window class for several messages (WM_GETMINMAXINFO, WM_NCCREATE, WM_NCCALCSIZE, WM_CREATE) before it returns. While the window procedure handles these messages the GWLP_USERDATA is not yet set. The system however guarantees, that GWLP_USERDATA is zero-initialized so you can safely query and handle the uninitialized GWLP_USERDATA.
If you want to set GWLP_USERDATA before CreateWindow[Ex] returns you will have to set up a CBT hook hook using SetWindowsHookEx and handle the HCBT_CREATEWND event. This lets you store any data attached to a HWND before the window procedure gets called with a WM_NCCREATE message.
Unrelated to your question, GWLP_USERDATA is fairly unreliable. A lot of applications will store their own data there, overwriting each other's data. Since this seems to be a private window class that you control you should allocate space in the Extra Window Memory instead and store your data there.
When I look in the Task Manager on the number of GDI objects for my process, then I see that not every call of function DeleteObject() for a GDI object causes decrementing this number, and the function call does not return FALSE (as it should if the object deletion was unsuccessful). I'm using plain Windows API GDI functions without additional libraries and wrappers such as MFC. Why such situation can happen and does it mean GDI resource leakage?
Here is the code how to recreate the problem:
void gditest()
{
HBRUSH h = CreateSolidBrush(RGB(255, 237, 5));
HRGN rgn = CreateRectRgn(0, 100, 100, 0);
FillRgn(g_DC, rgn, h);
int before = GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS);
int rs = DeleteObject( h );
if ( !rs )
throw;
int after = GetGuiResources(GetCurrentProcess(), GR_GDIOBJECTS);
}
Variables 'before' and 'after' are equal. g_DC is the HDC of the main window.
Stock GDI objects are never created nor destroyed. They are maintained by Windows and you can use them as you wish. If you have code like the following
HPEN hPen = (HPEN)GetStockObject(BLACK_PEN);
DeleteObject(hPen);
you will not see the GDI count go up or down. The call to DeleteObject will return TRUE even though the object is not really deleted.
If you want to check for resource leaks you can place calls to GetGuiResources in your code to compare the before/after values. You would typically place those calls where the resource counts should match, i.e. creation and destruction of resources match.
You should select a NULL object to Device Context before deleting the object.
Example:
SelectObject(g_DC, GetStockObject(NULL_BRUSH));
DeleteObject(h);
I wrote this piece of code to print a bitmap to my dialog box in an MFC program (C++ in Visual Studio 2010):
//Loop start
{
//...
//some prep stuff
//...
HBITMAP hBmp = myObv->GetBMP();
CBitmap bmp;
bmp.Attach(hBmp);
CClientDC dc(this);
CDC bmDC;
bmDC.CreateCompatibleDC(&dc);
CBitmap *pOldbmp = bmDC.SelectObject(&bmp);
BITMAP bi;
bmp.GetBitmap(&bi);
dc.BitBlt(384,26,bi.bmWidth/3,bi.bmHeight,&bmDC,0,0,SRCCOPY);
bmDC.SelectObject(pOldbmp);
}
This works fine except that as I continuously run the program and more bitmaps get drawn, the program very rapidly (linerally) begins to chew away at my available memory:
Obviously the rapid drop is me closing the program.
But when I try to delete some of the objects to try to stop the memory leak, my program crashes.
Ex: If I do
delete hBmp;
I get the error:
or if I delete pOldbmp, I get the error:
If I declare these objects outside the loop and just keep reusing them, I get fatal abort errors:
What's the deal??
Why can't I delete these objects?
Use DeleteObject(hBmp) instead.
This is happening because you're attempting to delete hBmp while still having selected it using SelectObject().
I was wondering, do I need to call DeleteObject in the following case?
CFont* oldFont = label.GetFont();
LOGFONT oldLogFont;
oldFont->GetLogFont(&oldLogFont);
oldLogFont.lfWeight = FW_BOLD;
CFont newFont;
newFont.CreateFontIndirectW(&oldLogFont);
label.SetFont(&newFont, true);
// Do I need to call oldFont->DeleteObject() or newFont->DeleteObject()?
Thanks.
No you don't. MFC classes are RAII classes. When the object drops out of scope (ie gets deconstructed) the object will be deleted appropriately.
I have an object, dc, of type CDC and I'd like to get an HDC object.
I read the MSDN documentation here, but don't really understand it.
Can someone provide me with a brief example/explanation on how to do this?
When you have CDC object it will be implicitly converted to HDC when necessary:
CDC dc;
HDC hdc = dc; // HDC hdc = dc.operator HDC();
If you have pointer to CDC object then using function GetSafeHdc will look more clear:
CDC* pdc = SOME;
HDC hdc = pdc->GetSafeHdc();
CDC class has operator HDC() defined which allows the compiler to convert a CDC object to HDC implicitly. Hence if you have CDC* and a function which takes HDC then you just dereference the pointer and send it to the function.
CDC is a C++ class which - to a reasonable approximation - encapsulates an HDC, which is a handle to a device context.
The documenation which you link to describes a conversion operator, which is a C++ construct that classes can supply to allow implicit conversion from an instance of a class to some other type. In this case the implicit conversion results in the underlying handle (HDC) which the CDC instance encapsulates.
You can perform the conversion by using a CDC instance anywhere were it needs to be converted to an HDC.
Most simply:
void f( const CDC& cdc )
{
HDC hdc = cdc;
// use hdc here
}
HDC hDC = dc;
Just assign it.
CDC cdc = something.
HDC hdc = cdc;
if (hdc != 0)
{
//success...
}