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().
Related
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.
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 couldn't find any function which removes a loaded icon. Please help me:))
Or is there any other function which makes an icon hidden such as setVisible(false), or delete?
if(GetDlgItem (IDC_BUTTON1)->IsWindowEnabled())
{
m_hIcon = AfxGetApp()->LoadIcon(IDI_ICON1);
dc.DrawIcon(DT_CENTER,DT_CENTER, m_hIcon);
}
if(GetDlgItem (IDC_BUTTON1)->IsWindowEnabled()==0) //disabled
{ dc.SetTextColor(RGB(192,192,192));
m_hIcon = AfxGetApp()->RemoveIcon(IDI_ICON1);//HERE! // I try another icon
//which is null, however it didn't work because it is transparent.
}
Instead of painting another icon when the button is disabled, either draw a rectangle using a null pen and a brush of the background colour or just invalidate the icon-rectangle with bErase as TRUE when you disable the button
This code is a bit strange, especially since you don't give us any context. What is dc, a device context? Is this code inside of a OnPaint message handler function? And either way, why are you drawing the icon manually instead of letting the button control do it automatically?
The simpler approach is to monitor the enabled state of the control by listening for WM_ENABLE messages via the OnEnable member function, and calling the SetIcon member function to update the button's icon. This way, the button control keeps track of the icon, so there's no need to keep it in a member variable (m_hIcon). And removing an icon is as simple as setting it to display a null icon. There's no need or all of these ugly hacks, like using a second transparent icon, or drawing over the icon with a solid color rectangle.
Sample code, where CMyButton extends CButton:
void CMyButton::OnEnable(BOOL bEnable)
{
CButton::OnEnable(bEnable); // call the base class
if (bEnable)
{
// The button was enabled, so load and set the icon.
const HICON hIcon = AfxGetApp()->LoadIcon(IDI_ICON1);
this->SetIcon(hIcon);
}
else
{
// The button was disabled.
// First, retrieve the current icon from the button.
const HICON hIcon = this->GetIcon();
// Then, remove the icon from the button by setting a null icon.
this->SetIcon(NULL);
// Finally, delete the original icon to prevent memory leaks.
::DestroyIcon(hIcon);
}
}
It is, of course, possible to do it your way inside of the OnPaint function, if you absolutely must (though this is poor design). The trick is that the icon only gets drawn if the code to draw it gets executed. Otherwise, no icon gets drawn. The base class will not draw an icon.
So all you need is:
void CMyWindow::OnPaint()
{
CPaintDC dc(this);
const CWnd* pBtn = GetDlgItem(IDC_BUTTON1);
if (pBtn->IsWindowEnabled())
{
m_hIcon = AfxGetApp()->LoadIcon(IDI_ICON1);
dc.DrawIcon(DT_CENTER, DT_CENTER, m_hIcon);
// make sure that you delete m_hIcon when the window is destroyed!
}
else
{
// Do not draw the icon here!
// But write whatever other code you want, like...
dc.SetTextColor(RGB(192,192,192));
}
}
Obviously this tactic will only work if your code is inside of the OnPaint function, but that is where you should do all of your drawing. Otherwise it will be lost whenever the window is repainted. For a demonstration, just try minimizing the window or moving it off the screen. Force a repaint by calling CWnd::Invalidate, followed by CWnd::UpdateWindow (or alternatively `CWnd::RedrawWindow).
I want to load a bitmap from file, perform some operations on it, and save it back under the same file name. The pattern is this:
Bitmap in = gcnew Bitmap(fileName);
Bitmap out = gcnew Bitmap(in.Width, in.Height, in.PixelFormat);
fill [out] with data from [in]
out.Save(fileName);
but this doesn't work. That's obvious. I cannot save to a file which is still opened (because of bitmap in). The question is: how the heck do I close bitmap in?! I've tried many ways but nothing works. Calling Dispose worked in C# but this method is protected in C++. Calling delete also doesn't work. What's the solution?
EDIT:
Operating on one bitmap doesn't work either. But I found a problem. Calling delete worked. I forgot to declare my bitmaps as pointers
Bitmap^ in = gcnew Bitmap(fileName);
Bitmap^ out = gcnew Bitmap(in.Width, in.Height, in.PixelFormat);
fill [out] with data from [in]
delete in;
out.Save(fileName);
This is a common trap in C++/CLI coding, you are using stack semantics. In other words, you didn't declare the reference type variable with the ^ hat. Which makes the compiler automatically emit the Dispose() call at the end of the scope block. Very convenient and a simulation of the RAII pattern in C++ but it gets in the way here. You want to dispose the in bitmap before saving the new bitmap.
Two ways to do this. You could play a game with the scope blocks by adding braces:
Bitmap^ out;
try {
{
Bitmap in(fileName);
out = gcnew Bitmap(in.Width, in.Height, in.PixelFormat);
// etc..
} // <== "in" gets disposed here
out->Save(fileName);
}
finally {
delete out;
}
But that's kinda ugly, especially since it needs to be mixed up for out in this very specific case. The alternative is to just do everything explicitly:
Bitmap^ out;
Bitmap^ in;
try {
in = gcnew Bitmap(fileName);
out = gcnew Bitmap(in->Width, in->Height, in->PixelFormat);
// etc..
delete in;
in = nullptr;
out->Save(fileName);
}
finally {
delete in;
delete out;
}
You don't need an out Bitmap. Just edit in and save it. Also I'd advise using the CImage class instead
CImage image;
image.Load(filename);
fill [image] with whatever data you want
image.Save(filename);
I have added a image (tiled) as a background to a class inheriting from wxPanel
Inside the constructor, the second line below is causing memory leakage, (reported in debug mode)
wxImage bg(_("images/textures/icobbg8.jpg"), wxBITMAP_TYPE_JPEG);
SetBackgroundBitmap(wxBitmap(bg));
If i comment the SetBackgroundBitmap memory leak is no longer reported.
Note - During debugging, and after viewing call stack i rounded on this statement.
Please tell me, how to overcome memory leak.
Your should call SetBackgroundBitmap(wxNullBitmap)
in your destructor
Class MyPanel:public wxPanel
{
MyPanel(wxWindow* parent, int x, int y, int w, int h);
~MyPanel();
};
MyPanel::~MyPanel()
{
SetBackgroundBitmap(wxNullBitmap); //set null bitmap backgrond, so not
//reference bg to overcome the leak
}
When the constructor exits, the wxImage bg will be destroyed. However, the class still exists and the background image is still needed.
Try changing the bg from a local to an attribute of the class.