473,387 Members | 1,501 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,387 software developers and data experts.

ptr in collection item

I have an Item object which allocates memory in its ctor
and frees it in its dtor.
I want to add such items to a vector. But the program crashes. Why?
How do I fix it?

#include <vector>

class Item
{
public:
int iId;
void* pMiscMem; // will be allocd in ctor and deallocd in dtor
Item(int AiId) : iId(AiId) { pMiscMem = malloc(1024); }
~Item() { free(pMiscMem), pMiscMem = 0; }
};

class MyColl
{
public:
std::vector<Item> v;
MyColl() {}
void Add(Item* pItem) { v.push_back(*pItem); }
};

void test_ptr_in_vector_item()
{
MyColl C;
for (int i = 0; i < 100; ++i)
C.Add(new Item(i));
}

Jul 23 '05 #1
13 1679
tuvok wrote:
I have an Item object which allocates memory in its ctor
and frees it in its dtor.
I want to add such items to a vector. But the program crashes. Why?
How do I fix it?


Read about "the Rule of Three".

V
Jul 23 '05 #2
Your copy constructor (automatically generated by the compiler) does not
allocate new memory. Are you trying to use heterogeneous containers like in
Java? You should avoid this.
Jul 23 '05 #3
"Victor Bazarov" wrote
tuvok wrote:
I have an Item object which allocates memory in its ctor
and frees it in its dtor.
I want to add such items to a vector. But the program crashes. Why?
How do I fix it?

Read about "the Rule of Three".


Thank you. I did and came up with the following but it still crashes :-(
What's missing?

class Item
{
public:
int iId;
void* pMiscMem; // will be allocd in ctor and deallocd in dtor

Item(int AiId) : iId(AiId), pMiscMem(0)
{ pMiscMem = malloc(1024); }

~Item()
{ free(pMiscMem), pMiscMem = 0; }

Item(const Item& Other)
{
free(pMiscMem);

iId = Other.iId;
pMiscMem = Other.pMiscMem;

Other.~Item();
}

const Item& operator=(const Item& Other)
{
free(pMiscMem);

iId = Other.iId;
pMiscMem = Other.pMiscMem;

Other.~Item();

return *this;
}
};

class MyColl
{
public:
std::vector<Item> v;
MyColl() {}
void Add(Item* pItem) { v.push_back(*pItem); }
};

void test_ptr_in_vector_item()
{
MyColl C;
for (int i = 0; i < 100; ++i)
C.Add(new Item(i));
}
Jul 23 '05 #4
"Jason Heyes" wrote
Your copy constructor (automatically generated by the compiler) does not
allocate new memory. Are you trying to use heterogeneous containers like in Java?


I think not. Cf. code. The container shall contain objects of the same one type.


Jul 23 '05 #5
Remove 'free(pMiscMem)' in your copy constructor and all lines containing
'Other.~Item()'.
Jul 23 '05 #6
tuvok wrote:
"Victor Bazarov" wrote
tuvok wrote:
I have an Item object which allocates memory in its ctor
and frees it in its dtor.
I want to add such items to a vector. But the program crashes. Why?
How do I fix it?
Read about "the Rule of Three".


Thank you. I did and came up with the following but it still crashes :-(
What's missing?

class Item
{
public:
int iId;
void* pMiscMem; // will be allocd in ctor and deallocd in dtor

Item(int AiId) : iId(AiId), pMiscMem(0)
{ pMiscMem = malloc(1024); }


Try using 'new' and delete[], rather than malloc() and free()?
Why is pMiscMem "void *", what will it hold?

~Item()
{ free(pMiscMem), pMiscMem = 0; }

Item(const Item& Other)
{
free(pMiscMem);

iId = Other.iId; pMiscMem = Other.pMiscMem;

This is a copy constructor, you should be making
a copy of "Other" - not taking over its data.
You should replace the above line with something
like this:

pMiscMem = malloc(1024);
memcpy(pMiscMem, Other.pMiscMem, 1024);

Otherwise you'll have 2 Item objects who's pMiscMem
pointers point to the same memory block. When either
of those Item objects is destructed, the memory that
both Item.pMiscMem members point to will be deleted.
That will leave the pMiscMem of the remaining 'Item'
object pointing to memory that already been freed;
causing a crash when the 2nd Item object is destructed.

Other.~Item();
Don't delete 'Other' in your copy constructor.
The purpose of the copy constructor is to make a copy
of 'Other' - and that's all.

}

const Item& operator=(const Item& Other)
{
free(pMiscMem);

iId = Other.iId; pMiscMem = Other.pMiscMem;
This is an assignmet operator, you should be making
a copy of "Other" - not taking over its data.
You should replace the above line with something
like this:

pMiscMem = malloc(1024);
memcpy(pMiscMem, Other.pMiscMem, 1024);

Otherwise you'll have 2 Item objects who's pMiscMem
pointers point to the same memory block. When either
of those Item objects is destructed, the memory that
both Item.pMiscMem members point to will be deleted.
That will leave the pMiscMem of the remaining 'Item'
object pointing to memory that already been freed;
causing a crash when the 2nd Item object is destructed.

Other.~Item();

Don't delete 'Other' in your assignment operator.
The purpose of the assignment operator is to make a
copy of the data from 'Other' in 'this' - and that's all.


return *this;
}
};

class MyColl
{
public:
std::vector<Item> v;
MyColl() {}
void Add(Item* pItem) { v.push_back(*pItem); }
};

void test_ptr_in_vector_item()
{
MyColl C;
for (int i = 0; i < 100; ++i)
C.Add(new Item(i));
}


Larry
Jul 23 '05 #7
tuvok wrote:
I have an Item object which allocates memory in its ctor
and frees it in its dtor.
I want to add such items to a vector. But the program crashes. Why?
How do I fix it?

#include <vector>

class Item
{
public:
int iId;
void* pMiscMem; // will be allocd in ctor and deallocd in dtor
Item(int AiId) : iId(AiId) { pMiscMem = malloc(1024); }
~Item() { free(pMiscMem), pMiscMem = 0; }
};

class MyColl
{
public:
std::vector<Item> v;
MyColl() {}
void Add(Item* pItem) { v.push_back(*pItem); }
};

void test_ptr_in_vector_item()
{
MyColl C;
for (int i = 0; i < 100; ++i)
C.Add(new Item(i));
}


There is a memory leak in the line:

C.Add(new Item(i));

You use 'new' to allocate an 'Item'.
A POINTER to that 'Item' is passed to Add() which
calls v.push_back(*pItem). push_back() makes a
COPY of it's arg (a copy of "*pItem" in this case),
then puts that copy into the vector. The original
'Item' allocated by 'new' is never deleted.
Here's one possible alternative:

void test_ptr_in_vector_item()
{
MyColl C;
Item * pItem;

for (int i = 0; i < 100; ++i)
{
pItem = new Item(i);
C.Add(pItem);
delete pItem;
}
}

The name 'test_ptr_in_vector()' is misleading.
You do not put a pointer to 'Item' (an "Item *")
in your vector; you put an actual 'Item'.

Larry
Jul 23 '05 #8
"Larry I Smith" wrote
tuvok wrote:
"Victor Bazarov" wrote
tuvok wrote:
I have an Item object which allocates memory in its ctor
and frees it in its dtor.
I want to add such items to a vector. But the program crashes. Why?
How do I fix it?

Read about "the Rule of Three".


Thank you. I did and came up with the following but it still crashes :-(
What's missing?

class Item
{
public:
int iId;
void* pMiscMem; // will be allocd in ctor and deallocd in dtor

Item(int AiId) : iId(AiId), pMiscMem(0)
{ pMiscMem = malloc(1024); }


Try using 'new' and delete[], rather than malloc() and free()?
Why is pMiscMem "void *", what will it hold?


Nothing special. Just a sample for demo purposes.

~Item()
{ free(pMiscMem), pMiscMem = 0; }

Item(const Item& Other)
{
free(pMiscMem);

iId = Other.iId;

pMiscMem = Other.pMiscMem;

This is a copy constructor, you should be making
a copy of "Other" - not taking over its data.
You should replace the above line with something
like this:

pMiscMem = malloc(1024);
memcpy(pMiscMem, Other.pMiscMem, 1024);

Otherwise you'll have 2 Item objects who's pMiscMem
pointers point to the same memory block. When either
of those Item objects is destructed, the memory that
both Item.pMiscMem members point to will be deleted.
That will leave the pMiscMem of the remaining 'Item'
object pointing to memory that already been freed;
causing a crash when the 2nd Item object is destructed.


Ok, got it.
But wouldn't it be faster if 'this' would just take the resources of 'Other'
and clear them in 'Other'? IOW transferring the ownership from
'Other' to 'this'. The following solution does it this way. Is it ok to do it so,
or is there anything against it?

class Item
{
public:
int iId;
void* pMiscMem; // will be allocd in ctor and deallocd in dtor

Item(int AiId) : iId(AiId)
{
pMiscMem = malloc(1024); // just a sample for ptr usage in collection items
}

~Item()
{
if (pMiscMem)
free(pMiscMem);
ClearOwnership();
}

void ClearOwnership()
{ // just clears the resources (but does not destroy them!)
// intended especially for ptrs.
// will be called from copy_ctor, assignment_operator, and dtor
pMiscMem = 0; // setting ptrs to 0 is important
iId = 0;
}

Item(const Item& Other)
{ // The object will be created (initialized) from the other one (Other),
// Therefore the normal ctor won't be called.
// So nothing is initialized yet!
// The initialization from Other is the job of this copy constructor.

// set resources of this from Other:
iId = Other.iId;
pMiscMem = Other.pMiscMem;

// take ownership by clearing Other:
((Item*) &Other)->ClearOwnership();
}

const Item& operator=(const Item& Other)
{
// free resources of this:
free(pMiscMem);

// set resources of this from Other:
iId = Other.iId;
pMiscMem = Other.pMiscMem;

// take ownership by clearing Other:
((Item*) &Other)->ClearOwnership();

return *this;
}
};

class MyColl
{
public:
std::vector<Item> v;
MyColl() {}
void Add(Item& rItem) { v.push_back(rItem); }
};

void test_ptr_in_vector_item()
{
MyColl C;
for (int i = 1; i <= 10000; ++i)
{
Item obj(i);
C.Add(obj);
}
}
Jul 23 '05 #9
"Larry I Smith" wrote
tuvok wrote:
I have an Item object which allocates memory in its ctor
and frees it in its dtor.
I want to add such items to a vector. But the program crashes. Why?
How do I fix it?
.... void test_ptr_in_vector_item()
{
MyColl C;
for (int i = 0; i < 100; ++i)
C.Add(new Item(i));
}

There is a memory leak in the line:

C.Add(new Item(i));

You use 'new' to allocate an 'Item'.
A POINTER to that 'Item' is passed to Add() which
calls v.push_back(*pItem). push_back() makes a
COPY of it's arg (a copy of "*pItem" in this case),
then puts that copy into the vector. The original
'Item' allocated by 'new' is never deleted.
Here's one possible alternative:

void test_ptr_in_vector_item()
{
MyColl C;
Item * pItem;

for (int i = 0; i < 100; ++i)
{
pItem = new Item(i);
C.Add(pItem);
delete pItem;
}
}


Thanks. Got it.
The name 'test_ptr_in_vector()' is misleading.
You do not put a pointer to 'Item' (an "Item *")
in your vector; you put an actual 'Item'.


Yeah. It better should be "test_ptr_in_collectionitem()"
Jul 23 '05 #10
tuvok wrote:
"Larry I Smith" wrote
tuvok wrote:
"Victor Bazarov" wrote
tuvok wrote:
>I have an Item object which allocates memory in its ctor
>and frees it in its dtor.
>I want to add such items to a vector. But the program crashes. Why?
>How do I fix it?
>
Read about "the Rule of Three".
Thank you. I did and came up with the following but it still crashes :-(
What's missing?

class Item
{
public:
int iId;
void* pMiscMem; // will be allocd in ctor and deallocd in dtor

Item(int AiId) : iId(AiId), pMiscMem(0)
{ pMiscMem = malloc(1024); }

Try using 'new' and delete[], rather than malloc() and free()?
Why is pMiscMem "void *", what will it hold?


Nothing special. Just a sample for demo purposes.
~Item()
{ free(pMiscMem), pMiscMem = 0; }

Item(const Item& Other)
{
free(pMiscMem);

iId = Other.iId;
pMiscMem = Other.pMiscMem;


This is a copy constructor, you should be making
a copy of "Other" - not taking over its data.
You should replace the above line with something
like this:

pMiscMem = malloc(1024);
memcpy(pMiscMem, Other.pMiscMem, 1024);

Otherwise you'll have 2 Item objects who's pMiscMem
pointers point to the same memory block. When either
of those Item objects is destructed, the memory that
both Item.pMiscMem members point to will be deleted.
That will leave the pMiscMem of the remaining 'Item'
object pointing to memory that already been freed;
causing a crash when the 2nd Item object is destructed.


Ok, got it.
But wouldn't it be faster if 'this' would just take the resources of 'Other'
and clear them in 'Other'? IOW transferring the ownership from
'Other' to 'this'. The following solution does it this way. Is it ok to do it so,
or is there anything against it?

class Item
{
public:
int iId;
void* pMiscMem; // will be allocd in ctor and deallocd in dtor

Item(int AiId) : iId(AiId)
{
pMiscMem = malloc(1024); // just a sample for ptr usage in collection items
}

~Item()
{
if (pMiscMem)
free(pMiscMem);
ClearOwnership();
}

void ClearOwnership()
{ // just clears the resources (but does not destroy them!)
// intended especially for ptrs.
// will be called from copy_ctor, assignment_operator, and dtor
pMiscMem = 0; // setting ptrs to 0 is important
iId = 0;
}

Item(const Item& Other)
{ // The object will be created (initialized) from the other one (Other),
// Therefore the normal ctor won't be called.
// So nothing is initialized yet!
// The initialization from Other is the job of this copy constructor.

// set resources of this from Other:
iId = Other.iId;
pMiscMem = Other.pMiscMem;

// take ownership by clearing Other:
((Item*) &Other)->ClearOwnership();
}

const Item& operator=(const Item& Other)
{
// free resources of this:
free(pMiscMem);

// set resources of this from Other:
iId = Other.iId;
pMiscMem = Other.pMiscMem;

// take ownership by clearing Other:
((Item*) &Other)->ClearOwnership();

return *this;
}
};

class MyColl
{
public:
std::vector<Item> v;
MyColl() {}
void Add(Item& rItem) { v.push_back(rItem); }
};

void test_ptr_in_vector_item()
{
MyColl C;
for (int i = 1; i <= 10000; ++i)
{
Item obj(i);
C.Add(obj);
}
}


Well, now you've changed the code considerably, and
induced additional (new) problems - like storing
references in a container, modifying 'const' objects,
etc, etc.

Exactly what is your real goal?

We can modify 'made up' play code all day long,
yet never answer your real question(s).

So again, what is the actual design requirement that you
are struggling to resolve?

Larry
Jul 23 '05 #11
"tuvok" <52***************@t-online.de> wrote in
news:d8*************@news.t-online.com:
Ok, got it.
But wouldn't it be faster if 'this' would just take the resources of
'Other' and clear them in 'Other'? IOW transferring the ownership from
'Other' to 'this'. The following solution does it this way. Is it ok
to do it so, or is there anything against it?


Uh... why aren't you simply using std::auto_ptr then? Sounds like it has
all of the semantics that you're looking for...

And... any pointer with a transfer of ownership semantics is unsuitable for
putting into the standard containers (note: auto_ptr included!). You might
want to look up something like boost::shared_ptr.
Jul 23 '05 #12
"Larry I Smith" wrote
tuvok wrote: .... Well, now you've changed the code considerably, and
induced additional (new) problems - like storing
references in a container, modifying 'const' objects,
etc, etc.
The storage of items via ref has not changed. Ie. objects
are stored as objects, not as pointers. This hasn't changed.
Exactly what is your real goal?


It was just the problem of safely adding "items with non-empty
pointer resources" to STL containers like vector.
IMO it is solved now by the use of a copy ctor.
Thanks everybody.
Jul 23 '05 #13
> It was just the problem of safely adding "items with non-empty
pointer resources" to STL containers like vector.
IMO it is solved now by the use of a copy ctor.
Thanks everybody.
NO. Read about why you can't put std::auto_ptr into STL containers.
The "transfer ownership" thing does not work if you store objects in
an STL container, since the container _does not_ guarantee to copy
the objects in a specific order so that the last-assigned-to object
is the one that is kept. You could end up with a container full of
empty ("cleared") objects.

And one other thing:
const Item& operator=(const Item& Other)
{
// free resources of this:
free(pMiscMem);

// set resources of this from Other:
iId = Other.iId;
pMiscMem = Other.pMiscMem;

// take ownership by clearing Other:
((Item*) &Other)->ClearOwnership();

return *this;
}


It might be wise to protect "operator =" against self assignment.
An STL container might well decide assign "x=x" - the above
code would screw up in that situation.
Jul 23 '05 #14

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

Similar topics

3
by: Marc L'Ecuyer | last post by:
Hi, I have a collection class derived from CollectionBase. This collection can add items of my class MyItem. In my class MyItem, I have a Selected property. When this property is set to true, I...
5
by: Kurt Bauer | last post by:
I have an ASP group calendar application which pulls calendar data from Exchange via webdav into an XML string. I then loop the XML nodes to populate a collection of appointments. Finally I use...
3
by: ck | last post by:
Sorry for the cross post. What is wrong with this code?--ado recordset to populate a collection--see reason below Dim myCol2 As New Collection On Error Resume Next Do While Not rs.EOF...
7
by: juli | last post by:
I have strings variables in a collection list and I want to create new collection but to add to it only strings that are distinct (no common strings). For example I have an object sentense which...
1
by: Josema | last post by:
Hi, My problem is the next one (in a windows application): - I have a class derived from collectionbase to fill with persons object (id, name) from database. - I have a ListBox wich datasource...
4
by: Michael K. Walter | last post by:
I'd like to create a strongly-typed collection of objects that are indexed by a string value (key is a string). I'd also like to allow users to iterate over the collection using a For-each loop...
3
by: Matt Michael | last post by:
I have a listview control and a collection object right now that I'm trying to pass information to and from. Whenever I click on the checkbox, I want it to remove certain listview items and add...
2
by: jmhmaine | last post by:
I've created a lookup class for a windows form application and I'm stuck on how on using the collection object. The process is simple, if the item is in the collection then return that object, if...
14
by: Rich | last post by:
Yes, I need to store some values in an array type collection object that can hold 3 or more parameters per index. I have looked at the collection object, hashtable object and would prefer not to...
6
by: Arthur Dent | last post by:
How do you sort a generic collection derived from System.Collections.ObjectModel.Collection? Thanks in advance, - Arthur Dent
0
by: taylorcarr | last post by:
A Canon printer is a smart device known for being advanced, efficient, and reliable. It is designed for home, office, and hybrid workspace use and can also be used for a variety of purposes. However,...
0
by: Charles Arthur | last post by:
How do i turn on java script on a villaon, callus and itel keypad mobile phone
0
by: aa123db | last post by:
Variable and constants Use var or let for variables and const fror constants. Var foo ='bar'; Let foo ='bar';const baz ='bar'; Functions function $name$ ($parameters$) { } ...
0
by: ryjfgjl | last post by:
If we have dozens or hundreds of excel to import into the database, if we use the excel import function provided by database editors such as navicat, it will be extremely tedious and time-consuming...
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
jinu1996
by: jinu1996 | last post by:
In today's digital age, having a compelling online presence is paramount for businesses aiming to thrive in a competitive landscape. At the heart of this digital strategy lies an intricately woven...

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.