|
But the fact is that my object file comes out the same so the compiler must be smart enough to know that it was an array pointer and uses the delete[] operator either way.
Gil
|
|
|
|
|
I just verified this in the debugger. It doesn't matter whether I use "delete" or "delete[]"...when I step into the delete call it jumps to the same place as shown below. The debugger doesn't detect a memory leak either way. Did you actually detect a memory leak or did you just look at the code and assume there was one? I agree that's what the msdn library says to do but in reality it's not making a difference.
void __cdecl operator delete(void* p)
{
#if !defined(_AFX_NO_DEBUG_CRT) && defined(_DEBUG)
_free_dbg(p, _NORMAL_BLOCK);
#else
free(p);
#endif
}
Gil
|
|
|
|
|
There is a HUGE difference. As huge as a difference between different runtimes (especially debug and release versions). Operators new and delete not necessary have to be implemented in terms of free and malloc. Here example of code, which hopefully will convince you to use delete[] with new[]. Build release version and run it from the command line. You will see that while 8 objects were constructed (and each allocated 128 bytes in constructor), only 1 was properly deleted (destructor was called). You have 128 x 7 = 896 bytes memory leak. Now add [] after delete, recomplile and see the difference.
=========== cut here ================
#include <iostream>
using std::cout;
using std::endl;
class CTest
{
public:
CTest() : m_p(new char[128])
{
cout << "Constructor" << endl;
}
~CTest()
{
cout << "Destructor" << endl;
delete[] m_p;
}
private:
char* m_p;
};
int main(int argc, char* argv[])
{
CTest* p = new CTest[8];
delete p; // OOPS!!!
return 0;
}
=========== cut here ================
az0te
|
|
|
|
|
I already changed my code to use delete[] but I just wanted to track down why I hadn't seen a memory leak in the OScope code. I talked to our C++ expert here at work and I now understand why. While using delete[] with new[] is the proper method it doesn't automatically mean you have a memory leak if you don't use delete[]....it depends on the array type. I agree that your example will cause a memory leak because the array type is a class that allocates memory with a destructor to free up that memory. But my code was using a built-in type so the compiler allocates a block of memory for the array and using delete will properly free up that entire memory block. Why don't you try your example using a double instead of the CTest class and see if you still have a memory leak?
Gil Jones
|
|
|
|
|
If you use double instead of CTest you won't have a memory leak. But this is true for only runtimes shipped with Visual Studio 6.0 and earlier. You cannot be 100% sure that this will be same for all other platforms and compilers. BTW, already in VS 7.1 if you write code like:
char* pch = new char[32];
delete pch;
and run it under debugger you will get an exception. Another scenario, when you overloading both new and delete operators and writing you own allocators.
As for the changes you made to OScope. The buffer you was allocating in InvalidateCtrl() wasn't freed and this was the source of the leak. This is why I wrote that you have to free it in destructor.
az0te
|
|
|
|
|
az0te is right.
delete []m_pdblDataPoints;
should be added to the destructor.
And add delete [] m_pdblSavedDataPoints; to InvalidateCtrl() as given below:
....
// copy the points
if( nPointsToCopy > 0 )
{
for( int i = nPointsToCopy-1; i >= 0; --i )
{
if(m_nDataIndex == 0)
m_nDataIndex = nOldBufferSize-1;
else
m_nDataIndex--;
m_pdblDataPoints[i] = m_pdblSavedDataPoints[m_nDataIndex];
}
// release the memory for the old data points
if( m_pdblSavedDataPoints != NULL )
delete [] m_pdblSavedDataPoints;
// reset the flags
if( bNewWrapFlag )
m_nDataIndex = 0;
else
m_nDataIndex = nPointsToCopy;
m_bWrapped = bNewWrapFlag;
}
else
if( m_pdblSavedDataPoints != NULL )
delete [] m_pdblSavedDataPoints;
....
|
|
|
|
|
Hi!
Autoranging !!
Great idea
Could you please forward me the changes.
e_mail:chen_ylu@yahoo.com.cn
Many thanx
chen_ylu
|
|
|
|
|
Hi! Autoranging !! Great idea Could you please forward me the changes.
Many thanx
Ike Bosch
|
|
|
|
|
Thanks for this great control, it works fine.
But I have a big application made with WTL Librairies, and I would like to know if some people have ported this control to a WTL control ? (I try it, but I'm not an expert and my project doesn't want compile )
Thanks in advance
Have a nice day
|
|
|
|
|
This is not a problem with your code, but is a problem that I face which affects the display of your code.
My program controls a multimeter type device and retrieves data from said device. I use your code to display the data in a nice form. But the problem is that when another window (let's call this window B) obscures the graphing window, and then window B is then minimized to un-obscure the graphing window, the graphing window does not repaint itself. More specifically, the whole graphing window is the shade of gray which is the background of the graphing window.
The pseudocode of part of my program is like this:
Cmd_send_Set_mulitmeter();
Cmd_send_Read_multimeter();
Is there a function I can call after the Read_multimeter() function which will repaint the graphing window so when some other window obscures it, the graphing window will repaint itself? I've used Invalidate() and InvalidateRect() without success. BTW, my program's main window is a dialog box, so the graph is in one corner of the main window. I am new to win32 programming, so please be kind! thanks!
|
|
|
|
|
I am playing with the program by changing the background, grid and plot colors.
If I set the following colors for background grid and plot, the grid cannot be drawn:
m_OScopeCtrl.SetBackgroundColor(RGB(0, 128, 128)) ;
m_OScopeCtrl.SetGridColor(RGB(0, 0, 0)) ;
m_OScopeCtrl.SetPlotColor(RGB(255, 0, 0)) ;
Can anyone tell me why?
Thanks.
Ke
|
|
|
|
|
The issue is most likely due to the combining of bitmaps. The control was written such that the grid is one bitmap and the plot is generated as another bitmap. The color depth of the bitmap may be an issue, or possibly the combination of bitmaps is wiping it out.
- Mark
|
|
|
|
|
Thanks for your kindly reply.
How can I solve it?
Regards,
Ke
|
|
|
|
|
you can use
memDC.BitBlt(0, 0,
m_nClientWidth, m_nClientHeight,
&m_dcPlot, 0, 0, SRCAND);
instead of
memDC.BitBlt(0, 0,
m_nClientWidth, m_nClientHeight,
&m_dcPlot, 0, 0, SRCPAINT);
in OnPaint() function
|
|
|
|
|
memDC.BitBlt(0, 0,
m_nClientWidth, m_nClientHeight,
&m_dcPlot, 0, 0, SRCAND); //SRCAND
doesn't work either.
Ke
|
|
|
|
|
thank you for your control....
but, it's memory leak..
um.... InvalidateCtrl();
maybe, it's serious memory leak????
|
|
|
|
|
Yes, the memory leaks can be found by using up
static CMemoryState oldstate, newstate, diffstate;
But I cannot find any clues to remove the leaks. Can anyone help?
Thanks.
|
|
|
|
|
I found a number of leaks when i ported this to win32 (non-MFC). nearly none of the GDI objects are deleted. Start by deleting any DC's that are created.
I found leaks in InvalidateCtrl (deleteDC) and DrawPoint (deleteDC). Don't forget to delete pens and brushes that are created and no longer needed.
|
|
|
|
|
I'm struggling to find a memory leak in a modified version of this control...
I was under the impression that the DC's destructor automatically deleted itself when out of scope, or am I mistaken? Also, shouldn't GDI objects be cleaned up in the same manner?
|
|
|
|
|
Please refer to the link below:
http://www.codeproject.com/KB/miscctrl/oscope.aspx?msg=2486704#xx2486704xx
cheers,
Ke
|
|
|
|
|
I would like to scroll back to see the initial data points?
1. If you can provide a way to dump the data to a file and later load the same to visualize the whole strip chart it would be cool.
2. If you can provide dynamic limit changes without affecting the current data, that feautre would be nice too.
I really appreciate the great work you have done.
PV
|
|
|
|
|
I set the dialog border resizeable and handled the WM_SIZE in the dialog as below.
if( m_OScopeCtrl.GetSafeHwnd() )
{
CRect rect;
GetClientRect(rect);
m_OScopeCtrl.MoveWindow(rect);
}
When the graph is running, if I resize the dialog the control resizes but graph stop working.
Any tips.
|
|
|
|
|
Wow, it is very old problem. I found the solution today morning. Anyway, please check below codes.
<<original codes="">>
///////////////////////////////////////////////////////////////////////////
void COScopeCtrl::Reset()
{
// to clear the existing data (in the form of a bitmap)
// simply invalidate the entire control
InvalidateCtrl() ;
}
<<my codes="">>
1. Add Reset(); to last of OnSize function.
2. Chage Reset function to below.
///////////////////////////////////////////////////////////////////////////
void COScopeCtrl::Reset()
{
// to clear the existing data (in the form of a bitmap)
// simply invalidate the entire control
if (m_pbitmapOldGrid != NULL)
m_dcGrid.SelectObject(m_pbitmapOldGrid) ;
if (m_pbitmapOldPlot != NULL)
m_dcPlot.SelectObject(m_pbitmapOldPlot) ;
// in case we haven't established the memory dc's
CClientDC dc(this) ;
// if we don't have one yet, set up a memory dc for the grid
if(m_dcGrid.GetSafeHdc() != NULL)
{
m_dcGrid.DeleteDC();
if(m_bitmapGrid.GetSafeHandle() != NULL)
m_bitmapGrid.DeleteObject();
m_dcGrid.CreateCompatibleDC(&dc) ;
m_bitmapGrid.CreateCompatibleBitmap(&dc, m_nClientWidth,
m_nClientHeight) ;
m_pbitmapOldGrid = m_dcGrid.SelectObject(&m_bitmapGrid) ;
}
if(m_dcPlot.GetSafeHdc() != NULL)
{
m_dcPlot.DeleteDC();
if(m_bitmapPlot.GetSafeHandle() != NULL)
m_bitmapPlot.DeleteObject();
m_dcPlot.CreateCompatibleDC(&dc) ;
m_bitmapPlot.CreateCompatibleBitmap(&dc, m_nClientWidth,
m_nClientHeight) ;
m_pbitmapOldPlot = m_dcPlot.SelectObject(&m_bitmapPlot) ;
}
InvalidateCtrl() ;
}
Is run? Good luck!
|
|
|
|
|
I noticed that this class has an OnSize handler. Is it possible to use this in a CView?
Any examples on how to do this?
M.
|
|
|
|
|
The COScopeCtrl is based on a CWnd, so it really is no different to used this in a view. Just create it the same way as the demo application, except you define/decide the CRect size and location rather than having a place holder for it. As for the OnSize handler, this gets called when the control is created. If you want the control to change size or position based on your view size, you can always call the m_OScopeCtrl.MoveWindow(newRect).
|
|
|
|