|
Tom, I for one would welcome (more) info on MFC's internals. And as you pointed out, real-world usage examples would come in *very* handy.
/ravi
"There is always one more bug..."
http://www.ravib.com
ravib@ravib.com
|
|
|
|
|
Sounds like a good idea.
There's a couple of people here (including me) who'd like to know more about MFC and how to apply it.
A problem I have is that I know what I want a program to do, but not how to achieve that in a windows environment. CP has helped a lot, but sometimes a book of 'typical' applications would help too
Paresh Solanki
There is no substitute for genuine lack of preparation.
|
|
|
|
|
dazinith wrote:
any help in general would be great.. i don't want to have any memory leaks..
Always a worthy goal
The way to track down memory leaks in an MFC application - short of spending hours and hours manually tracking down and tracing on every new and delete operation - is to use the CMemoryState class. There are actually several ways to use this class so instead of me enumerating them all, I'll just point you to the article entitled "Taking Memory Snapshots" in your MSDN online help.
Good luck! Everybody hates those *#*& things!
Cheers,
Tom Archer
Author, Inside C#
A total abstainer is one who abstains from everything but abstention, and especially from inactivity in the affairs of others.
|
|
|
|
|
Make sure you have no code that looks like
CObArray vec;
for (int i = 0; i < vec.GetSize(); i++)
{
delete vec[i];
vec.RemoveAt(i);
} where just every other element is deleted. This one I've seen lots of times.
|
|
|
|
|
my deleting of CObArray's looks like this
// delete all items in the text list
if (m_oaText->GetSize() > 0)
do
{
CTextPrintObject* pObj = (CTextPrintObject*)m_oaText->GetAt(0);
delete pObj;
m_oaText->RemoveAt(0);
} while (m_oaText->GetSize() > 0);
m_oaText->RemoveAll();
delete m_oaText;
does this look right?
-dz
|
|
|
|
|
Sure looks functional enough. (Even though quite inefficient calling RemoveAt(0), since the array has to do a copy of all remaining items for each turn in the loop. Maybe you should consider looping backwards.)
Does you CTextPrintObject allocate any memory, not deleted in it's destructor?
|
|
|
|
|
After having read Tom's post, I think I'd write this as:
for (long nIndex=0; (nIndex < m_oaText->GetSize()); nIndex++) {
CTextPrintObject* pObj = (CTextPrintObject*) m_oaText->GetAt(nIndex);
ASSERT (pObj != NULL);
delete pObj;
m_oaText->SetAt (nIndex, NULL);
}
delete m_oaText;
/ravi
"There is always one more bug..."
http://www.ravib.com
ravib@ravib.com
|
|
|
|
|
welp i think i found where the leak is.. but i don't know whats wrong with the code.. if i comment out this chunk of code i only get 1 memory leak.. if i dont comment it out i get 8.. anyone have any suggestions as to whats wrong with this? basicly im just setting dates for a couple date pickers..
//Setup the date picker
m_cdPeriodEnd.SetFormat(_T("MM/dd/yyyy")); // force short date format to MM/dd/yyyy
m_cdPeriodBegin.SetFormat(_T("MM/dd/yyyy"));
COleDateTime dtMin(2002,7,31,0,0,0); // set the minimum date which can be chosen
COleDateTime dtMax(2003,6,30,0,0,0); // set the maximum date which can be chosen
// verify the min and max dates are valid, then set the range for the date picker
if ((dtMin.GetStatus() == COleDateTime::valid) && (dtMax.GetStatus() == COleDateTime::valid))
{
m_cdPeriodEnd.SetRange(&dtMin,&dtMax);
m_cdPeriodBegin.SetRange(&dtMin,&dtMax);
}
else
{
if (dtMin.GetStatus() != COleDateTime::valid)
AfxMessageBox("This program has attempted to set an invalid minimum date for selection.");
if (dtMax.GetStatus() != COleDateTime::valid)
AfxMessageBox("This program has attempted to set an invalid maximum date for selection.");
CDialog::EndDialog(IDABORT);
}
-dz
|
|
|
|
|
hrm.. nevermind i don't think thats it.. i think i should be able to track it down, thanks for the advice, and thanks for letting me know about deleting brushes too!
thanks!
-dz
|
|
|
|
|
Try this console code, it demonstrates C Runtime Library on memory leak detection.
#include <iostreamᡊe9ac73-238b-46be-991d-0f050c37248d#include <crtdbg.hᡊe9ac73-238b-46be-991d-0f050c37248d
using namespace std;
void main()
{
_CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF);
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT);
int* p = new int;
*p = 4;
p = 0;
delete p;
}
Maxwell Chen
No code is good code.
|
|
|
|
|
and if you defines #define _CRTDBG_MAP_ALLOC before any includes, you also get the line where you allocated the (not free'd) memory...
- Anders
Money talks, but all mine ever says is "Goodbye!"
|
|
|
|
|
But when I applied those functions
_CrtSetDbgFlag(_CRTDBG_LEAK_CHECK_DF | _CRTDBG_ALLOC_MEM_DF);
_CrtSetReportMode(_CRT_WARN, _CRTDBG_MODE_FILE);
_CrtSetReportFile(_CRT_WARN, _CRTDBG_FILE_STDOUT); in MFC app projects, set the debug argument to redirect the report to some txt file like MemLkRpt.txt , nothing's reported in that file. How should I do, like: when should these _CrtSet???( ) functions be called, in the ctor of theApp, or some other where? Any additional steps must be taken? ... etc.
And by the way, I can not delete the generated MemLkRpt.txt file!
Thanks
Maxwell Chen
No code is good code.
|
|
|
|
|
Serialization can also give memory leaks. If your not 100% sure about whats going on.
If you have an object that can be created dynamically from serialization you could do this:
CMyObject *pObject = new CMyObject ;
ar >> pObject ;
... stuff
delete pObject ;
The problem here is that your new ed object is lost as the serialization code allocates another object itself dynamically.
Roger Allen
Sonork 100.10016
If I had a quote, it would be a very good one.
|
|
|
|
|
I want to set up an #if condition based on a environment variable,
anyone know if it's possible to set up such a thing?
(I'm using VC6)
/Magnus
|
|
|
|
|
I don't believe so. Retrieving an environment variable would entail running code. The #if is a preprocessor directive that is resolved at compile-time, before your code runs.
Cheers,
Tom Archer
Author, Inside C#
A total abstainer is one who abstains from everything but abstention, and especially from inactivity in the affairs of others.
|
|
|
|
|
Yes, that i am aware of, i tought maybe someone knew of some wierd
#pragma directive or similar that did the trick.
Looks like i have to do some .bat file that runs nmake.
(Back to the 80's )
/Magnus
|
|
|
|
|
Either that or maybe write a preprocessor-like app whose sole job is to inspect an environment variable and update a #define in a global header file. The advantage being that you would still be able to use the normal VS/VC make. I don't know how to inject a processor into the mix, but I'm sure that it can be done.
Cheers,
Tom Archer
Author, Inside C#
A total abstainer is one who abstains from everything but abstention, and especially from inactivity in the affairs of others.
|
|
|
|
|
That sonud like a nicer soultion.
I'll will try and fine some pre-compile place where i can hook the thingy in.
/Magnus
|
|
|
|
|
Actually, thinking more about it now. You would think that writing an add-in that does what I'm proposing here (updating a global file's #define) and then using the VS object model to kick off the build. THat would give you the best of both worlds (an add-in vs a preproccesor) and would be a solution that is already documented (the writing of add-ins). I would think that that would be easier than finding dox on preprocessing. What do you think?
Cheers,
Tom Archer
Author, Inside C#
A total abstainer is one who abstains from everything but abstention, and especially from inactivity in the affairs of others.
|
|
|
|
|
I agree that that sounds like the most elegant solution.
However for now im just looking for the fastest way to get it
working and that way would require me to dig in to DevStudio add-in writing.
I'll probably will do it the 'proper' way when i got some more time over.
/Magnus
|
|
|
|
|
I hear you, mate. Unfortunately deadlines often get in the way of the cool stuff we want to write
Cheers,
Tom Archer
Author, Inside C#
A total abstainer is one who abstains from everything but abstention, and especially from inactivity in the affairs of others.
|
|
|
|
|
If you are using DevStudio I can see two possible ways:
1) VB Macro. They are simple to write but I don't know if VB has the methods needed to read the environment. There is an object to control the build, the BuildProject object.
2) Developer Studio Add-In. This is a compiled .dll so I you could do anything here that C/C++ allows you to do. Problem is they are more complex to write then a macro. But there are some nice examples on CodeProject.
Good luck,
David
|
|
|
|
|
That might be a way to do it.
If VB dont have the requried methods thay can easily be added trough a COM object
I'll ponder on the options for a while.
/Magnus
|
|
|
|
|
(smack forehead) DOH! Much better than my recommended way. An add-in or macro would be the best way to do it. Nice suggestion!
Cheers,
Tom Archer
Author, Inside C#
A total abstainer is one who abstains from everything but abstention, and especially from inactivity in the affairs of others.
|
|
|
|
|
Do you mean :
int num = 3;
if(num == 5)
#define _A
#undef _B
{ }
else
#define _B
#undef _A
{ }
#if defined(_A)
cout << "_A defined.\n";
#endif
#if defined(_B)
cout << "_B defined.\n";
#endif
The result is :
_B defined.
Maxwell Chen
No code is good code.
|
|
|
|