 |
BorlandTalk.com Borland discussion newsgroups
|
| View previous topic :: View next topic |
| Author |
Message |
Paw Suddergaard Guest
|
Posted: Thu Dec 22, 2005 1:35 pm Post subject: Vector problems... |
|
|
Hi! - Iv'e got a few problems with some vectors im using..
My .h file:
........
struct TGParams{
std::vector<Class1*> Vector;
String Name;
String Group;
};
std::vector<TGParams*> GroupVec;
........
Ok.. I create about 20 items(TGParams) in the GroupVec.
The TGParams->Vector has several thousands of pointers to Class1
Objects, there are also NULLS in the vector sometimes...
My problem is when i try to free/cleanup the memory...
This DOESN'T WORK:(I get an error in the vector.h file)
while(!GroupVec.empty())
{
while(!GroupVec.back()->Vector.empty())
{
if(GroupVec.back()->Vector.back())
delete GroupVec.back()->Vector.back();
GroupVec.back()->Vector.pop_back();
}
delete GroupVec.back();
GroupVec.pop_back();
}
AND This DOESN'T WORK: (I get an error in the vector.h file)
for(int a=0;a<GroupVec.size();a++){
for(int i=0;i
{
delete &GroupVec[a]->Vector[i];
}
GroupVec[a]->Vector.clear();
}
GroupVec.clear();
PLEASE HELP!
Thanks,
Paw
|
|
| Back to top |
|
 |
Chris Uzdavinis (TeamB) Guest
|
Posted: Thu Dec 22, 2005 1:52 pm Post subject: Re: Vector problems... |
|
|
Paw Suddergaard <paw (AT) top-house (DOT) dk> writes:
| Quote: | Hi! - Iv'e got a few problems with some vectors im using..
My .h file:
.......
struct TGParams{
std::vector<Class1*> Vector;
String Name;
String Group;
};
std::vector<TGParams*> GroupVec;
Ok.. I create about 20 items(TGParams) in the GroupVec.
The TGParams->Vector has several thousands of pointers to Class1
|
Ok...
| Quote: | Objects, there are also NULLS in the vector sometimes...
|
Is that on purpose? If not, you should figure out why and fix the bug
that is causing this.
| Quote: | My problem is when i try to free/cleanup the memory...
|
What problem? You mention a problem, you say things "don't work" but
you do not give even a slight hint what the problem is that you're
having. You are asking for help yet wanting us to have to guess to
provide help, which is unreliable at best.
Please, ALWAYS post compiler error messages if you experience them, or
if you have a runtime error, say precisely what it is!
| Quote: | This DOESN'T WORK:(I get an error in the vector.h file)
|
What error?
| Quote: | while(!GroupVec.empty())
{
while(!GroupVec.back()->Vector.empty())
{
if(GroupVec.back()->Vector.back())
delete GroupVec.back()->Vector.back();
GroupVec.back()->Vector.pop_back();
}
delete GroupVec.back();
GroupVec.pop_back();
|
This is not a good way to do it. You're having to fetch the back()
element on GroupVec too many times, and repeated function calls should
usually be called just once with cached results for efficiency.
Better, find another way to accomplish what you're doing.
Since you know the vector is going to be destroyed as soon as you
finish looping through it, there is no good reason to waste the time
of popping all the elements out of the vector. Well, truly pedantic
reasons may exist, like on some platforms leaving an invalid address
in a pointer can caus undefined behavior even if you only read the
address, but that's such an esoteric problem as to be easily
dismissed.
However, the point is you should find a better way. A simple loop
over the elements is a better approach. But I'd suggest for the best
approach, stop managing the memory like this, and use a smart pointer
to do it for you. That is, use something like boost::shared_ptr to
hold your TGParams pointers, and also to hold your Class1 pointers.
| Quote: | AND This DOESN'T WORK: (I get an error in the vector.h file)
for(int a=0;a<GroupVec.size();a++){
for(int i=0;i
{
delete &GroupVec[a]->Vector[i];
|
Why are you deleting the address of the element in your Vector? (And
why do you call the member Vector, which indicates nothing about what
or why it exists, only how it holds whatever it holds? Consider a
better variable name)
| Quote: | }
GroupVec[a]->Vector.clear();
}
GroupVec.clear();
|
Here's an idea for using the shared_ptr from boost:
#include "boost/shared_ptr.hpp"
//....
typedef boost::shared_ptr<Class1> Class1_shptr;
struct TGParams{
std::vector< Class1_shptr > Vector;
String Name;
String Group;
};
typedef boost::shared_ptr< TGParams > TGParams_shptr;
std::vector<TGParams_shptr> GroupVec;
Then remove ALL of your code that deletes elements. It'll happen
automatically. You just have to download Boost (www.boost.org) and be
sure to put it into your include path, such that the boost_1_33
directory (or whatever it's called) which holds the
"boost/shared_ptr.hpp" file is in your path.
--
Chris (TeamB);
|
|
| Back to top |
|
 |
Liz Albin Guest
|
Posted: Thu Dec 22, 2005 1:52 pm Post subject: Re: Vector problems... |
|
|
On Thu, 22 Dec 2005 14:35:29 +0100, Paw Suddergaard wrote:
| Quote: | for(int a=0;a<GroupVec.size();a++){
for(int i=0;i
{
delete &GroupVec[a]->Vector[i];
}
GroupVec[a]->Vector.clear();
}
GroupVec.clear();
|
It would be helpful for you to construct an actual example of the
problem, rather than offering code snippets. Some things spring to
mind though.
- did you actually allocate all the pointers?
- does Class1's destructor get rid of any allocations?
- consider using boost::shared_ptr instead of raw pointers.
That way you don't have to worry about allocation/deallocation
http://www.boost.org/libs/smart_ptr/shared_ptr.htm
- setting deleted objects to null
Do you do this?
- typedefs
e.g.
typedef std::vector <TGParams *¨> TGParamV;
typedef std::vector <TGPârams * >::iterator TGParamI;
etc
and use the types for:
- iterators
try something like: (totally untested)
for ( TGParamI a = GroupVec.begin(); a != GroupVec.end(); ++a)
{
for (TClass1I b = (*a).Vector.begin(); b != (*a).Vector.end(); ++b )
{
TClass1 *thing = b;
delete thing;
thing = NULL;
}
}
--
liz
|
|
| Back to top |
|
 |
Andrue Cope [TeamB] Guest
|
Posted: Thu Dec 22, 2005 2:48 pm Post subject: Re: Vector problems... |
|
|
Paw Suddergaard wrote:
| Quote: | struct TGParams{
std::vector<Class1*> Vector;
String Name;
String Group;
};
std::vector<TGParams*> GroupVec;
|
I always dislike storing pointers to things in STL containers. It
causes hassle where there was none. One option would be to implement
your own copy ctors and assignment operators but that can be
problematic.
I'd favour the lazy man's approach:
struct TGParams
{
std::vector<boost::shared_ptr Vector;
String Name;
String Group;
};
std::vector<TGParams> GroupVec;
I would expect boost::shared_ptr to take care of ownership of your
'Class1's for you. 'String' assuming it's the expected type already
knows how to take care of itself. The result is that TGParams now
becomes STL container compatible. You can just stuff things into
GroupVec, sort them and take them out as you see fit without needing to
worry about ownership.
Disclaimer:It's getting near holiday time so my brain might not be
functioning at its best. It looks feasable to me atm though
--
Andrue Cope [TeamB]
[Bicester, Uk]
http://info.borland.com/newsgroups/guide.html
|
|
| Back to top |
|
 |
Duane Hebert Guest
|
Posted: Thu Dec 22, 2005 9:49 pm Post subject: Re: Vector problems... |
|
|
"Paw Suddergaard" <paw (AT) top-house (DOT) dk> wrote
| Quote: | This DOESN'T WORK:(I get an error in the vector.h file)
|
Not sure what this means but at any rate, reporting the error
may help.
| Quote: | while(!GroupVec.empty())
{
while(!GroupVec.back()->Vector.empty())
{
if(GroupVec.back()->Vector.back())
delete GroupVec.back()->Vector.back();
GroupVec.back()->Vector.pop_back();
}
delete GroupVec.back();
GroupVec.pop_back();
}
|
This one is way to complicated to comment on except
why all the back()/pop_back() stuff? Why continually
call empty()?
| Quote: | AND This DOESN'T WORK: (I get an error in the vector.h file)
for(int a=0;a<GroupVec.size();a++){
for(int i=0;i
{
delete &GroupVec[a]->Vector[i];
}
GroupVec[a]->Vector.clear();
}
GroupVec.clear();
|
This is closer to a more "normal" approach but...
What is the delete &GroupVec[a]->Vector[i] for?
It's hard to see from these snippets why you can just
say delete GroupVec[a]->Vector[i]. i.e why the reference?
Assuming that for some reason you don't want to
take the lazy way and use shared pointers,
why not just iterate through each and call delete?
Create an iterator to the outer one. Loop through,
Create an iterator for the inner one. Call delete on
the iterator. When your done, call clear.
It would be helpful if you posted the error in the second
case.
|
|
| Back to top |
|
 |
Paw Suddergaard Guest
|
Posted: Tue Dec 27, 2005 2:01 pm Post subject: Re: Vector problems... |
|
|
Hi all!
Thanks for your reply's. Sorry i wasn't more specific, but i was writing
the post just before i was going home to my chrismas holliday.
Anyway i've changed my code so that i'm now using vector.push_back().
Before i Resized the vector to a specific size and then i filled it like
an array. (vector[somewhere] = somthing)
Push_back seems to be more the "correct" way to do it.
(all though it takes a little longer...)
Now when i want to delete i use this method:
for(int a=0;a<GroupVec.size();a++){
for(int i=0;i
{
delete GroupVec[a]->Vector[i];
GroupVec[a]->Vector[i] = 0;
}
GroupVec[a]->Vector.clear();
delete GroupVec[a];
GroupVec[a] = 0;
}
GroupVec.clear();
Not shure if this is correct, but a buddy of mine suggested it, so now
im trying it.
My problem now is when the program wants to execute :
"delete GroupVec[a]->Vector[i];"
It takes so long time... Im talking about minutes...
And when i've got between 10.000 and 100.000 objects, thats just not
usable...
So now im thinking: should i try using the Boost::shared_ptr like some
of you said and then not delete the objects myself, or does anybody have
an explanation to why it takes so long?
I havent used Boost before and it will be a bit of recoding if i have to
- thats why im still trying to do it the "normal" way.
Thanks again,
/Paw
|
|
| Back to top |
|
 |
Liz Albin Guest
|
Posted: Tue Dec 27, 2005 2:08 pm Post subject: Re: Vector problems... |
|
|
On Tue, 27 Dec 2005 15:01:59 +0100, Paw Suddergaard wrote:
| Quote: | And when i've got between 10.000 and 100.000 objects, thats just not
usable...
|
really, look at boost::shared_ptr (in boost.org)
then you won't have to do any of the deletion, it's handled for you.
--
liz
|
|
| Back to top |
|
 |
Eelke Guest
|
Posted: Tue Dec 27, 2005 2:55 pm Post subject: Re: Vector problems... |
|
|
Paw Suddergaard wrote:
| Quote: | Hi all!
Thanks for your reply's. Sorry i wasn't more specific, but i was writing
the post just before i was going home to my chrismas holliday.
Anyway i've changed my code so that i'm now using vector.push_back().
Before i Resized the vector to a specific size and then i filled it like
an array. (vector[somewhere] = somthing)
Push_back seems to be more the "correct" way to do it.
(all though it takes a little longer...)
With vectors you can use reserve to pre-allocate memory. It will only |
allocate memory unlike resize which changes the actual number of items
in the vector. When you reserve the right amount of items you can save
some expensive memory reallocations.
| Quote: |
Now when i want to delete i use this method:
for(int a=0;a<GroupVec.size();a++){
for(int i=0;i
{
delete GroupVec[a]->Vector[i];
GroupVec[a]->Vector[i] = 0;
}
GroupVec[a]->Vector.clear();
delete GroupVec[a];
GroupVec[a] = 0;
}
GroupVec.clear();
Not shure if this is correct, but a buddy of mine suggested it, so now
im trying it.
It looks good. The lines |
GroupVec[a]->Vector[i] = 0;
and
GroupVec[a] = 0;
could be left out as you are going to clear the vectors anyway.
| Quote: |
My problem now is when the program wants to execute :
"delete GroupVec[a]->Vector[i];"
It takes so long time... Im talking about minutes...
For one object or for a 100.000 objects?
And when i've got between 10.000 and 100.000 objects, thats just not
usable...
So now im thinking: should i try using the Boost::shared_ptr like some
of you said and then not delete the objects myself, or does anybody have
an explanation to why it takes so long?
It depends a bit on the objects you are deleting. For each object you |
delete the objects destructor is called and also all destructors of
member variables. For instance your struct TGParams contains two
Strings. A String has a destructor which will be called when the
TGParams is deleted.
Using a boost::shared_ptr will not make it any faster.
Eelke
|
|
| Back to top |
|
 |
Paw Suddergaard Guest
|
Posted: Tue Dec 27, 2005 3:08 pm Post subject: Re: Vector problems... |
|
|
| Quote: | really, look at boost::shared_ptr (in boost.org)
then you won't have to do any of the deletion, it's handled for you.
|
Hi Liz,
Thanks, i've downloaded boost and are now using it. I've got a few
questions though:
1. reset(); - Does this "reset" the pointer, like setting a pointer to
NULL?, cause in my code i use alot of conditions testing on NULL pointers.
2. If i call clear() on a vector containing shared_ptr's will i then
force the destruction of my objects? - Cause i need a way to control
when i destroy the object, so i can free my memory...
typedef boost::shared_ptr<Class1> Class1_shptr;
struct TGParams{
std::vector<Class1_shptr> Vector;
String Name;
String group;
};
typedef boost::shared_ptr<TGParams> TGParams_shptr;
std::vector<TGParams_shptr> TGParams_shptrVec;
So if i call "shptrVec.clear()" I will then free all the memory of all
the objects also the ones in the "std::vector<Class1_shptr> Vector" ?
Thanks again!
/Paw
|
|
| Back to top |
|
 |
Liz Albin Guest
|
Posted: Tue Dec 27, 2005 3:16 pm Post subject: Re: Vector problems... |
|
|
On Tue, 27 Dec 2005 16:24:56 +0100, Paw Suddergaard wrote:
| Quote: | Yes, but my idea was that because i have to fill in 100.000 objects i
would be faster if the vector had the right size in the first place...
|
You can create it at whatever size...
--
liz
|
|
| Back to top |
|
 |
Paw Suddergaard Guest
|
Posted: Tue Dec 27, 2005 3:24 pm Post subject: Re: Vector problems... |
|
|
Hi Elke,
Thanks for your reply!
| Quote: | With vectors you can use reserve to pre-allocate memory. It will only
allocate memory unlike resize which changes the actual number of items
in the vector. When you reserve the right amount of items you can save
some expensive memory reallocations.
|
Yes, but my idea was that because i have to fill in 100.000 objects i
would be faster if the vector had the right size in the first place...
| Quote: | It looks good. The lines
GroupVec[a]->Vector[i] = 0;
and
GroupVec[a] = 0;
could be left out as you are going to clear the vectors anyway.
|
OK...
| Quote: | For one object or for a 100.000 objects?
|
For just 1 object. And the object is not that big, it has a couple
pointers and about 6 long ints...
| Quote: | Using a boost::shared_ptr will not make it any faster.
|
I'm trying it right now, and it seems to work better though.
/Paw
|
|
| Back to top |
|
 |
Chris Uzdavinis (TeamB) Guest
|
Posted: Tue Dec 27, 2005 3:26 pm Post subject: Re: Vector problems... |
|
|
Paw Suddergaard <paw (AT) top-house (DOT) dk> writes:
| Quote: | really, look at boost::shared_ptr (in boost.org)
then you won't have to do any of the deletion, it's handled for you.
Hi Liz,
Thanks, i've downloaded boost and are now using it. I've got a few
questions though:
1. reset(); - Does this "reset" the pointer, like setting a pointer to
NULL?, cause in my code i use alot of conditions testing on NULL
pointers.
|
http://www.boost.org/libs/smart_ptr/shared_ptr.htm
| Quote: | 2. If i call clear() on a vector containing shared_ptr's will i then
force the destruction of my objects? - Cause i need a way to control
when i destroy the object, so i can free my memory...
|
If you're using a shared_ptr, then you don't need to free your memory,
it will be done automatically, when the shared_ptr is destroyed.
Clearing a vector will destroy the elements it contains.
| Quote: | typedef boost::shared_ptr<Class1> Class1_shptr;
struct TGParams{
std::vector<Class1_shptr> Vector;
String Name;
String group;
};
typedef boost::shared_ptr<TGParams> TGParams_shptr;
std::vector<TGParams_shptr> TGParams_shptrVec;
So if i call "shptrVec.clear()" I will then free all the memory of all
the objects also the ones in the "std::vector<Class1_shptr> Vector" ?
|
All of your TGParams objects will be destroyed, which will also mean
that the Vector subobjects and their elements will be destroyed.
However, The TGParams_shptrVec object itself has allocated some memory
that may not be deallocated. It isn't leaked, but is saved for future
use. Until you actually destroy a vector the memory it allocates is
not guaranteed to go away when you clear it (but the elements it holds
are guaranteed to be destroyed.)
The solution is to do this instead of (or in addition to) just
clearing it:
std::vector<TGParams_shptr>().swap(TGParams_shptrVec);
It creates a new empty vector and swaps the elements out of your
original one and into the temporary. Simultaneously, the contents of
the temporary vector--which is empty--are put into the original
vector. The net result is that your original vector is left empty,
and the temporary variable immediately goes out of scope and is
destroyed, destroying the old elements along with it, and deallocating
the memory.
--
Chris (TeamB);
|
|
| Back to top |
|
 |
Chris Uzdavinis (TeamB) Guest
|
Posted: Tue Dec 27, 2005 3:37 pm Post subject: Re: Vector problems... |
|
|
Paw Suddergaard <paw (AT) top-house (DOT) dk> writes:
| Quote: | Yes, but my idea was that because i have to fill in 100.000 objects i
would be faster if the vector had the right size in the first place...
|
You can, either tell it the number of objects to default construct:
std::vector<int> v(10000); // hold 10000 ints (initialized to zero)
Or
std::vector<int> v;
v.reserve(10000); // allocate enough memory to hold 10000 ints, but
// don't actually change the vector.
for (int i=0; i < 10000; ++i)
v.push_back(get_some_value(i));
There is no resizing involved in this approach, so it will be faster.
--
Chris (TeamB);
|
|
| Back to top |
|
 |
Paw Suddergaard Guest
|
Posted: Tue Dec 27, 2005 3:52 pm Post subject: Re: Vector problems... |
|
|
Hi Chris!
Thanks for your reply.
void reset(); // never throws
Effects: Equivalent to shared_ptr().swap(*this).
I'm sorry, but i'm not really shure what that means. What is "*this"?
Will the pointer be reset to "nothing" or?
| Quote: | std::vector<TGParams_shptr>().swap(TGParams_shptrVec);
|
Cool! I've just tried it, and in my test case i allocate about 10 MB of
Memory, Calling this i free about 5... So the last 5 is Overhead? Memory
that will be reused?
Thanks again!
/Paw
|
|
| Back to top |
|
 |
Liz Albin Guest
|
Posted: Tue Dec 27, 2005 5:02 pm Post subject: Re: Vector problems... |
|
|
On Tue, 27 Dec 2005 16:08:31 +0100, Paw Suddergaard wrote:
| Quote: | So if i call "shptrVec.clear()" I will then free all the memory of all
the objects also the ones in the "std::vector<Class1_shptr> Vector" ?
|
shared_ptr will destroy the underlying pointer when the last object
holding them is destroyed
Please check the examples for details of usage..
http://www.boost.org/libs/smart_ptr/example/shared_ptr_example.cpp
the basic answer to you questions is that you don't have to worry
about the memory usage.
Period.
--
liz
|
|
| Back to top |
|
 |
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
|