473,561 Members | 3,336 Online
Bytes | Software Development & Data Engineering Community
+ Post

Home Posts Topics Members FAQ

Please Help: can't deallocate a vector of heap objects

Dear all,
I don't understand why "delete" works well on destructing a object, but
fails to destruct a vector of it. Any of your comment is highly
appreciated!
Following is the program that represent this problem:
=============== =============== ===========
int main (int argc, char *argv[])
{
FILE *input_file = fopen64 (argv[1], "r"); //input file is 216Mb,
//10 millon lines
[... initialize some variables here ..]
vector<m_op*> mVec; // a vector of pointer to m_op objects
//this loop will parse each input line into a m_op object,
//and then insert them into a vector
while (fgets (intput_line, 30, input_file) != NULL) //read in a line
{
[... assign values a,b,c from input_line ...]
m_op* ptr = new m_op (a, b, c);
mVec.push_back( ptr);
}
[break point #1] <- process memory size: 801Mb
//size of 10 million m_op objects

//this loop will delete on each object in the vector
for (vector<m_op*>: :iterator it = mVec.begin();
it != mVec.end(); it++)
{
delete (*it);
}
mVec.clear();
[break point #2] <- process memory size: 763Mb //shouldn't be 0Mb?
}
=============== =============== =============== =========
The input file is 216Mb, with 10 million lines. The first loop will
create a m_op object for each input line. At [break point #1], I use
"top" to inspect the process, and find that it takes 801Mb memory
space. So I expect after running the second loop, it will be something
close to zero. However, after the second loop, at [break point #2], the
process still holds 763Mb. Obviously, the vector has been cleared, but
the 10 million objects still remain in the memory. I can not figure out
why the destructor didn't free up the memory space.

However, if I put
the statement "delete ptr" right after it's "new", into a single loop,
the memory will always remain 808Kb, which means that the destructor
has worked properply.
=============== =============== =============== =========
while (fgets (intput_line, 30, input_file) != NULL)
{
[... assign values a,b,c from input_line ...]
m_op* ptr = new m_op (a, b, c);
delete (ptr);
}
=============== =============== =============== =========
The constructor and destructor is simply:
m_op::m_op(int cyc, string &rw, string &addr)
:_cycle_no(cyc) ,
_rw(rw),
_m_addr(addr),
{
}
m_op::~m_op()
{
}
=============== =============== =============== ========
I got no clue why destructor works well on a single object, but failed
to deallocate a vector of object.
The environment is RedHat Linux, x86, gcc 3.2.2, compiled with:
g++ -o prog1 main.cc -g
Any of your comment or help is highly appreciated!
Many thanks,
Charlie

Jul 23 '05 #1
10 2264
go*********@yah oo.com wrote:
I don't understand why "delete" works well on destructing a object,
but fails to destruct a vector of it. Any of your comment is highly
appreciated!
Following is the program that represent this problem:
=============== =============== ===========
int main (int argc, char *argv[])
{
FILE *input_file = fopen64 (argv[1], "r"); //input file is 216Mb,
//10 millon lines
[... initialize some variables here ..]

[..]
[break point #1] <- process memory size: 801Mb
//size of 10 million m_op objects
[..]
[break point #2] <- process memory size: 763Mb //shouldn't be 0Mb?
[..]


Whatever conclusions you try to draw from "process memory size", it has
no bearing on whether 'delete' works or not. Those are two totally
unrelated things. The memory may become available inside your process
but not to other processes. Or the OS may decide to make it available
to everybody. It's not in the language, it's in the platform. Please
ask for assistance in comp.os.linux.d evelopment.apps .

V
Jul 23 '05 #2

<go*********@ya hoo.com> wrote in message
news:11******** **************@ z14g2000cwz.goo glegroups.com.. .
Dear all,
I don't understand why "delete" works well on destructing a object, but
fails to destruct a vector of it. Any of your comment is highly
appreciated!
Following is the program that represent this problem:
=============== =============== ===========
int main (int argc, char *argv[])
{
FILE *input_file = fopen64 (argv[1], "r"); //input file is 216Mb,
//10 millon lines
[... initialize some variables here ..]
vector<m_op*> mVec; // a vector of pointer to m_op objects
//this loop will parse each input line into a m_op object,
//and then insert them into a vector
while (fgets (intput_line, 30, input_file) != NULL) //read in a line
{
[... assign values a,b,c from input_line ...]
m_op* ptr = new m_op (a, b, c);
mVec.push_back( ptr);
}
[break point #1] <- process memory size: 801Mb
//size of 10 million m_op objects

//this loop will delete on each object in the vector
for (vector<m_op*>: :iterator it = mVec.begin();
it != mVec.end(); it++)
{
delete (*it);
}
mVec.clear();
[break point #2] <- process memory size: 763Mb //shouldn't be 0Mb?


Look up the subjects "scope" and "lifetime of objects" and then the
difference between "stack" and "heap" and when and how these allocations are
recovered (thats not what delete does).

Better yet, compile a program that does nothing, allocates nothing and set a
breakpoint on the return. What are your findings?

Then explain to us why a running program's process should somehow not be
occupying a given chunk of memory. Or is it your beleif that breakpoint #2
does not occur in a running program?
Jul 23 '05 #3
gogogo_1...@yah oo.com wrote:

I don't understand why "delete" works well on destructing a
object, but fails to destruct a vector of it.
The objects are destructed correctly. But you are misinterpreting
what your debugger is showing you.
int main (int argc, char *argv[])
{
while (fgets (intput_line, 30, input_file) != NULL)
{
m_op* ptr = new m_op (a, b, c);
mVec.push_back( ptr);
}

[break point #1] <- process memory size: 801Mb
//size of 10 million m_op objects

//this loop will delete on each object in the vector
for (vector<m_op*>: :iterator it = mVec.begin();
it != mVec.end(); it++)
delete (*it);
mVec.clear();

[break point #2] <- process memory size: 763Mb //shouldn't be 0Mb?
This is an operating system issue. When you deallocate memory,
there is no requirement that the process return it to the
operating system.
However, if I put the statement "delete ptr" right after it's
"new", into a single loop, the memory will always remain 808Kb
Because the process only ever has one object in existence at
once, it only needs to request memory for one object from
the operating system. When you allocate the second object,
it re-uses the memory from the first object.

If you don't allocate any objects at all, you will probably
find the memory used is slightly less than 808Kb.
Any of your comment or help is highly appreciated!


Have you considered storing the objects in the vector, rather
than pointers? This will save you four bytes per object
(ie. 40Mb), and makes your job as a coder a lot easier.

Also, technically you should remove a pointer from the
vector before you delete it. If you delete a pointer while
it is in a vector, then the vector contains an indeterminate
value, and this could cause undefined behaviour (even if
the only thing you do to the vector is clear it).

For example:
for (vector<m_op*>: :iterator it = mVec.begin();
it != mVec.end(); it++)
{
m_op *ptr = 0;
std::swap(*it, ptr);
delete ptr;
}
mVec.clear();

Also note that clear() on a vector isn't required to free
the memory used by the vector. To do that, you have to destroy
the vector; one convenient way to do that is:

mVec.swap( std::vector<m_o p*>() );

Jul 23 '05 #4
I know this doesn't answer your question, but couldn't you just say
mVec.push_back( m_op(a,b,c)) where mVec is a simple vector<m_op> ??

That way you would never have to delete anything.

Samee

Jul 23 '05 #5
Old Wolf wrote:
Also, technically you should remove a pointer from the
vector before you delete it. If you delete a pointer while
it is in a vector, then the vector contains an indeterminate
value, and this could cause undefined behaviour (even if
the only thing you do to the vector is clear it).

For example:
for (vector<m_op*>: :iterator it = mVec.begin();
it != mVec.end(); it++)
{
m_op *ptr = 0;
std::swap(*it, ptr);
delete ptr;
}
mVec.clear();

Also note that clear() on a vector isn't required to free
the memory used by the vector. To do that, you have to destroy
the vector; one convenient way to do that is:

mVec.swap( std::vector<m_o p*>() );


Why sooo complicated?

const T* t = vector.back();
vector.pop_back ();
delete t;
::A::

Jul 23 '05 #6
Abecedarian wrote:
Old Wolf wrote:
Also, technically you should remove a pointer from the
vector before you delete it. If you delete a pointer while
it is in a vector, then the vector contains an indeterminate
value, and this could cause undefined behaviour (even if
the only thing you do to the vector is clear it).

For example:
for (vector<m_op*>: :iterator it = mVec.begin();
it != mVec.end(); it++)
{
m_op *ptr = 0;
std::swap(*it, ptr);
delete ptr;
}
mVec.clear();

Why sooo complicated?

const T* t = vector.back();
vector.pop_back ();
delete t;


Your code only deletes one item, and causes UB if the vector
is empty. My code deletes all items safely.
If you extend your code to work correctly, then I think
it is at least as 'complicated' as mine.

Jul 23 '05 #7
Old Wolf wrote:
Your code only deletes one item, and causes UB if the vector
is empty. My code deletes all items safely.
If you extend your code to work correctly, then I think
it is at least as 'complicated' as mine.


while (!vector.empty( )) {
const T* t = vector.back();
vector.pop_back ();
delete t;
}

At least it doesn't copy (swap) objects unnecessarily.

::A::

Jul 23 '05 #8
Thank you sooo much! Eventually, I got this problem fixed. I stored
the objects directly into the vector.

My first thought was to use the code like this:
=============== ===========
while (fgets (intput_line, 30, input_file) != NULL) //read in a line
{
[... assign values a,b,c from input_line ...]

m_op tmp(a, b, c);
mVec.push_back( tmp);
}
=============== =============
After a reading Samee Zahur's post, I realised that it is incorrect, as
the push_back(const &T), is call by reference, so the next iteration of
the loop will overide tmp, so mVec[1] is referencing the same object as
mVec[0].
Creating a nameless object is better. Later on if I want to refer to
it, I can use mVec's iterator.
=============== =
After "swap" the vector with a empty vector, the memory size has
greatly shrinked, to 380Mb. So I was confused how this couldn't free
them up? I also tried clear(), = emptyVec()... None worked.

Eventually, I found that there is another problem with the string, as
mVec has 2 string members, after calling ~string(), they still do not
free up the memory. So I changed to Char[], now, eventually, everyting
is fine.

This is the hardest bug I've ever met. And gave me lots of lessons.
- always prefer premitive data type than STL
- push_back is call by &, so if you call it multiple times in a loop,
create anonymous object, so the object names wouldn't be overiden.
- process wouldn't return claimed heap memory back to OS, same true for
malloc and free. But things are different for stack objects.
- Not to be superstition, but sometime, the bug might really not come
from your code
- use swap to free vector
- ...

Many thanks all of you for your kind suggestions!!!
Best regards,
Charlie

Jul 23 '05 #9
go*********@yah oo.com wrote:
Thank you sooo much! Eventually, I got this problem fixed. I stored
the objects directly into the vector.

My first thought was to use the code like this:
=============== ===========
while (fgets (intput_line, 30, input_file) != NULL) //read in a line
{
[... assign values a,b,c from input_line ...]

m_op tmp(a, b, c);
mVec.push_back( tmp);
}
=============== =============
After a reading Samee Zahur's post, I realised that it is incorrect, as
the push_back(const &T), is call by reference, so the next iteration of
the loop will overide tmp, so mVec[1] is referencing the same object as
mVec[0].


When you put an object in an STL container (list, vector, set, etc)
The STL makes a copy of the object and stores that copy; it does
not store the original. That's why objects to be stored in
containers need to have (at least):

- a public copy constructor
- a public default constructor
- a public destructor
- a public assignment operator.

Regards,
Larry

--
Anti-spam address, change each 'X' to '.' to reply directly.
Jul 23 '05 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

4
3842
by: Greg Baker | last post by:
I don't know what standard protocol is in this newsgroup. Am I allowed to post code and ask for help? I hope so.. :) Here's my problem: I am trying problem 127 of the valladolid online contests (http://online-judge.uva.es/p/v1/127.html). The program I wrote seems to work fine, but it takes way too much memory to run. I am not that...
5
2296
by: Kenneth W Del Signore | last post by:
Hi, I'm working on a scheme to store several millions of records (Subdata), each of which contains a variable number of sub records (Celldata). My concern is that my prototype uses a lot more memory than I'm expecting. To store 1.7million Subdatas that have an average of 7 Celldatas, I'm using 85 Mb. Thats about 50 bytes/record, where as...
11
2884
by: Richard Thompson | last post by:
I've got a memory overwrite problem, and it looks as if a vector has been moved, even though I haven't inserted or deleted any elements in it. Is this possible? In other words, are there any circumstances in which the STL will move a vector, or invalidate iterators to elements in the vector, if you don't insert or remove elements? My actual...
14
1636
by: HP | last post by:
Hi All i have confussion regarding given problem please help me out 4. What happens with the following program: void main(){ myclass* pmc = new myclass; pmc = 0; delete pmc;}
6
6589
by: Dolphin White | last post by:
For example, I allocate some unmanaged resources in the static constructors, then how can I properly release the resource before the application exit? thx!
13
1850
by: linux_bp | last post by:
I have an stl vector array which stores the pointers to objects. To delete the array i am using: std::vector<*foo> bar; .... for (vector<*foo>::iterator itr = bar.begin(); itr != bar.end(); ) { delete itr; itr = NULL; }
5
1828
by: aaragon | last post by:
Hello everybody, I appreciate your taking the time to take a look at this example. I need some help to start the design of an application. To that purpose I'm using policy-based design. The idea is to have a Class that stores elements of Class2 in different ways (arrays in stack memory, arrays in heap memory, using the std::vector and so...
17
4479
by: Jess | last post by:
Hello, The iterator adaptor "back_inserter" takes a container and returns a iterator so that we can insert elements to the end of the container. Out of curiosity, I tried to look at what element the returned iterator refers to. Here is my code: #include<iostream> #include<vector> #include<iterator>
48
5551
by: Ward Bekker | last post by:
Hi, I'm wondering if the GC.Collect method really collects all objects possible objects? Or is this still a "smart" process sometimes keeping objects alive even if they can be garbage collected? I need to know because I'm looking for memory leaks in an application. It would be really helpful to be able to determine if an object after...
0
7639
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However, people are often confused as to whether an ONU can Work As a Router. In this blog post, we’ll explore What is ONU, What Is Router, ONU & Router’s main...
0
7855
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers, it seems that the internal comparison operator "<=>" tries to promote arguments from unsigned to signed. This is as boiled down as I can make it. ...
1
7608
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows Update option using the Control Panel or Settings app; it automatically checks for updates and installs any it finds, whether you like it or not. For...
1
5465
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new presenter, Adolph Dupré who will be discussing some powerful techniques for using class modules. He will explain when you may want to use classes...
0
5181
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and then checking html paragraph one by one. At the time of converting from word file to html my equations which are in the word document file was convert...
0
3613
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The last exercise I practiced was to create a LAN-to-LAN VPN between two Pfsense firewalls, by using IPSEC protocols. I succeeded, with both firewalls in...
0
3594
by: adsilva | last post by:
A Windows Forms form does not have the event Unload, like VB6. What one acts like?
1
2058
by: 6302768590 | last post by:
Hai team i want code for transfer the data from one system to another through IP address by using C# our system has to for every 5mins then we have to update the data what the data is updated we have to send another system
1
1172
muto222
by: muto222 | last post by:
How can i add a mobile payment intergratation into php mysql website.

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.