|
Oops! v was meant to be the OCTETSTR parm, sorry. Change the function header to this:
void OctetStrToHexString(OCTETSTR v, CString& sResult)
--
jlr
http://jlamas.blogspot.com/[^]
|
|
|
|
|
I'm trying to rewrite a console application with more efficiency and I am getting nailed by memory assertions. The biggest difference is that I'm deriving my own objects from CObject and my own list from CObList but that's not where I'm having a problem. I wrote my own iterator but something is calling it's destructor and goes down in flames. I have this now:
<br />
Iterator * iterator = new Iterator();<br />
<br />
for (iterator->Clear(); (!(iterator->MaximumValueReached())); (*iterator)++) {<br />
... does work ...<br />
}<br />
The iterator code works fine in the previous version of the code and I didn't touch it since then. Execution happens once through then goes back up to the for, it iterates fine, exits to the above for loop and immediately enters the destructor. The only time I delete this iterator (on purpose) is in the destructor of the class member this code is in and that's much later.
Also, in the iterator I have a pointer to a struct. The struct exists by using 'new' and it crashes when I 'delete' it.
To note: I was having problems by an assertion being thrown because _CrtCheckMemory returns false which I found out means that there is some counter that counts my mallocs and when it hits 1023, it throws the assertion. This problem mentioned at the beginning of this message started occuring before this assertion so I don't have access to that problem but the two might be related. I might start by changing my old malloc/free statements to new/delete.
Any help to this would be much appreciated. I don't know why I'm getting memory issues just by a couple class derivation rewrites, hopefully you can help me.
|
|
|
|
|
Why are you reinventing the wheel like this ?
Christian Graus - Microsoft MVP - C++
|
|
|
|
|
Well,
1. I used to use a 64-bit integer to do this earlier but that would limit me not only by size but by portability.
2. I also wanted to try out overloading operators because I've never done that.
3. Lastly, I need it to do a lot more than a simple single variable does and placing all the extra functionality with the iterator is very convenient for me.
|
|
|
|
|
Some suggestions:
- Set a breakpoint at the Iterator destructor and check the call stack to see why and from where it's being destructed. If the debugger breaks too often because you have many other iterators, which also get destructed, you may qualify the breakpoint with a condition (e.g.: this==[iterator of interest]) so that the debugger will only break when that particular Iterator is being destructed.
- Just a hunch, but check if somewhere in your code (in particular, in the body of that for loop), you aren't unintentionally assigning the iterator to another pointer on which you later call delete. For example, if you write something like if (anotherIterator = iterator) instead of if (anotherIterator == iterator) .
--
jlr
http://jlamas.blogspot.com/[^]
|
|
|
|
|
- I did set a breakpoint and the call stack is going from the line and file of the for loop I mentioned and directly to the destructor.
- That iterator is never touched anywhere else except through a single function called Test which simply reports a sequence of bitwise AND operations with the iterator data and another smaller for loop index variable.
Thanks for your reply. I do have a feeling the problem is with something dumb I did but I keep saying to myself "there is no way this code is wrong".
|
|
|
|
|
Is the for loop exactly like the one you posted? Or did you post a simplified version? If so, post the actual code, and maybe the entire function in which it's enclosed (unless it's very big). Someone may have more luck at spotting a problem.
--
jlr
http://jlamas.blogspot.com/[^]
|
|
|
|
|
That loop is exactly as you see it (minus changing the increment from pre-increment to post-increment), but the entire function is too big to post it all.
|
|
|
|
|
LighthouseJ wrote:
(!(iterator->MaximumValueReached()));
Ahhh! Go back to studying the basics of C++. I've never seen any body allocate an iterator before (makes no since). Also, what guarantees that the iterator is still valid (at the above point).
All I see in your example, is code that is guaranteed to crash.
INTP
"The more help VB provides VB programmers, the more miserable your life as a C++ programmer becomes."
Andrew W. Troelsen
|
|
|
|
|
This class is more of just an iterator embedded in a class with members in it. That function, MaximumValueReached() does work in my earlier project. About those guarantees, I did some checking and found out when it finishes the iterator, the data in it gets corrupted. I have a pre-increment and post-increment operator and here's the code that did it:
Iterator& Iterator::operator++ () {<br />
... does iteration here ...<br />
return *this;<br />
}<br />
<br />
Iterator Iterator::operator++ (int) {<br />
Iterator temp = *this;<br />
++(*this);<br />
return temp;<br />
}
In my for loop, I was calling the post-increment operator which in turn calls the pre-increment operator. I think VC knows how to shape the machine code to increment before or after. What was happening is that the code would get to '++(*this);' and go into the pre-increment and work fine then exit back to the post-increment operator. Before the 'return temp;' statement, the iterator is fine, but after it ran the return statement, it's corrupted and I don't know how it became corrupted or deleted since it's running it's own destructor.
I did switch the for statement to the pre-increment iterator and it works until I hit the debug assertion
_ASSERTE(_CrtCheckMemory()); which I said in my first post that I was receiving before. I've read on some sites like MSDN that says it "Confirms the integrity of the memory blocks allocated in the debug heap (debug version only).". I also read that every time you malloc, it adds one to a counter and when that counter is 1 less than 1024 it asserts. I read what this assertion does but it (and web sites) offer no solution to fix it that I can find.
|
|
|
|
|
LighthouseJ wrote:
// post-increment
Iterator Iterator::operator++ (int) {
Iterator temp = *this;
++(*this);
return temp;
}
There are two copy of Iterator operations there, one when you do temp = *this and another when you return temp . Does Iterator have a copy constructor or operator= ?
You mentioned before that Iterator contains a pointer to a heap-allocated structure, which it deletes in the Iterator destructor. How are these structures copied when you copy one Iterator to another? If it's only copying the pointer (instead of allocating a new structure based on the original), the destructor of the local variable temp would do a delete on the structure, and that would be the same one pointed to by the Iterator you are returning and also the same one pointed by the original Iterator ...
--
jlr
http://jlamas.blogspot.com/[^]
|
|
|
|
|
I see what you and John R Shaw mention in the next message that I am making a new iterator and when it's created, the data isn't carried forth. No, I only overloaded the 2 increment operators because that's all I want the iterator to do, it's never compared with another, nor will I be decrementing. Doing pre- or post- really doesn't change the function of the programming controlling the iterator, I just incorporated the source from a site and went on from there. I am currently looking into the copy constructor now in hopes I can understand that new concept as well.
I believe I now have a handle on this problem and that the other problem about the _CrtCheckMemory assertion is still plaguing me. As I mentioned before, I read what the function does but I don't understand what causes the assertion, or as some sites mention, what causes the heap to be corrupted. At the time of assertion, the call stack leaves my program at the point where I add an item to a CObList. The added item is valid when it leaves my code, the CObList it's added to is valid but empty at the moment, it's adding the first item to the list. My program creates a class I made derived from CObList. The constructor creates a new CObList, things are added, work is done and if the results pass a test, it's kept and the old is deleted. The destructor removes all items from that list and deletes the CObList itself then ends. Where am I going wrong here? I can paste some code or further explain something if clarification is needed.
|
|
|
|
|
I was looking on the web and I found a replacement memory manager that basically does what VC does but it records a log of every allocation and deallocation (or reallocation). If there's a memory allocation/deallocation mismatch or a memory leak, it creates a log file so you can inspect the problem further. It tells you the line that each item is allocated or deallocated.
If you're interested in checking it out, go to fluidstudios.com and download their Memory Manager aka MMGR, put the files into your project, compile and run. If there's a memory problem, it will cause a breakpoint, if the problem is minor like a memory leak, it will let the execution complete but write out a text file log describing the memory leak.
|
|
|
|
|
I see Jose Lamas Rios already gave a reasonable answer. Even without the automatic destuction in the post-increment code it is still possible for your code to increment passed the end (off into la la land). A normal interator does basicaly that, except it has a specific (invalid) ending point that you can check to see if you are done.
As for pre-increment and post-increment operator: You are not correct about what the compiler can do. A compiler can shape the code on known types such as int, double, ect..; it is incapable of determining how to convert a post-increment to a pre-increment for user defined types. Therefore, you should make using a pre-increment a habit or you'll constantly be making (hidden) temporary copies of what ever you are incrementing.
INTP
"The more help VB provides VB programmers, the more miserable your life as a C++ programmer becomes."
Andrew W. Troelsen
|
|
|
|
|
Without knowing how Iterator was written it's hard to say what's wrong.
The (*iterator)++ looks weird on an object pointer - i hope Iterator overloads operator ++ () and/or operator ++ (int).
...cmk
Save the whales - collect the whole set
|
|
|
|
|
Yes, I got example code for doing both pre- and post-increment from a site on the web and used that code in my project.
|
|
|
|
|
Hi,
I have
========================
in vb.net
========================
Public Structure aStructure
public k as short
public b as short
public c as string
End Structure
Sub WriteStructure()
Dim txtfName As String
txtfName = "c:\rStruct.txt"
FileOpen(FreeFile(), txtfName, OpenMode.Binary, OpenAccess.Write)
FilePut(1, rStructure)
FileClose(1)
End Sub
================================
in c++, read in the structure
================================
struct astruct
{
int k;
int b;
CString c;
};
void main()
{
astruct *rStructure = new(struct astruct);
CString fName = "c:\\rStruct.txt";
aStructure = new(struct astruct);
FILE *rFile
rFile = fopen(fName, "r");
if(File)
{
fread(rStructure,sizeof(struct astruct),1,rFile);
fclose(rFile);
}
}
Do not really know why the structure wasnt' fill in right when it reads in (c++ code)? Only the first member 'k' was read in right. what am I doing wrong?
Thank you.
|
|
|
|
|
k,b are ints where in VB they are shorts. Also, you can't read a VB string into a CString like that.
Tim Smith
I'm going to patent thought. I have yet to see any prior art.
|
|
|
|
|
so how should I read then?
|
|
|
|
|
First, I appologize if the answer is here somewhere but I couldn't find it. I am trying to find out where in my program I have a GDI object leak. As I run my program, the task manager reports that my GDI object count is rising. I have been programming VC++ since 4.0 and I am very verse in deleting my objects when I am done with them. However, I have run into a case where I believe it is in a Win32 call that may make a copy. I just don't know which one.
For example, I just learned that CStatic::SetIcon makes a copy. I have an array of HICONs that are loaded in App::InitInstance and destroyed in App:ExitInstance. Everytime I call a CStatic::SetIcon with one of these icon handles, the GDI object count increases. The fix was to do a GetIcon first, and DeleteObject on the icon handle it returns. Program is happy now in that regard.
But I still am missing some and I was wondering where. The program is graphic intensive and would be tough to start selectively commenting out the graphic calls.
Any thoughts?
|
|
|
|
|
Are you running the debug kernel of windows?
In the old days (I mean 1994/1995) if you did so, when your process exited, if you had not freed all the GDI objects, you would get a dump when running your process under debug mode of all the GDI object you failed to 'free'.
You might also find this utility helpful:
http://msdn.microsoft.com/msdnmag/issues/03/01/GDILeaks/default.aspx[^]
|
|
|
|
|
I am using WindowsXP with latest patches, etc. The task manager GDI Object count increases when I open a particular dialog box, for example. This dialog box has many CStatic-based elements which I use for some icon displays (that change based on some user WM_ events). It also has CButton-based elements for some metal-looking buttons with regions and icons. I started commenting out different pieces, trying to isolate the issue. The icons change while the dialog is open and the GDI Object count increases. It stays at that level when the dialog is closed but goes up yet again when the dialog is re-opened. To complicate matters more, I use a CMemDC to draw on before BitBlt-ing onto the CDC provided in the OnDraw.
I wouldn't necessarily have an issue with this but if the program runs for hours, I get low system resource errors, the program fails to paint windows, and eventually locks up. It seems to happen more frequently when I am in front of customers. Task manager is the only way to kill it.
I will look into the article you mentioned. I also looked at different tools (Rational Purify, Numega, etc.) but they are expensive.... I may have no alternative.
Thanks!
|
|
|
|
|
MFC uses a lot of object caching.
As a result, you can't use the values in the Task Mgr as an accurate account of what 'you' have freed as MFC may still have the object cached. It makes it rather hard to find any real leaks.
...cmk
Save the whales - collect the whole set
|
|
|
|
|
I was wondering about that. I did see some cases where the count would linger before going down. However, I have some cases where it jumps up by 30 to 40 and then stays put (see response to Blake above). It gets bigger and bigger as the program stays running and eventually I get system resource errors and the program hangs.
|
|
|
|
|
prcarp wrote:
appologize
No need! If you feel the need, it implies you know what you're doing, but have not figured out the answer yet!
It would help if you posted the leak error message.
If it is happening in debug mode, the odds are that the leak reported is invalid. Since the task manager reports that the count is rising, then it probably is real. Before assuming the task manager is telling you the entire truth: give it a few minutes or try closing the IDE, to see if the task manager stops reporting the same count. If the task manager does report the same count, then try running a release version of your application and see if the same thing is still happening.
Assuming (ass-u-me) that the problem is in the code you wrote, then I would put a TRACE(...) statement wherever you create a GDI object as well as where you release/free the GDI object (to see if they match).
There is also the possibility that you selected a pen, brush, ect... and did not restore the original (unlikely).
Oh Well! I dought if any of this helped (you already knew it).
INTP
"The more help VB provides VB programmers, the more miserable your life as a C++ programmer becomes."
Andrew W. Troelsen
|
|
|
|