For Programmers: Free Programming Magazines  


Home > Archive > VC STL > August 2005 > map









You are viewing an archived Text-only version of the thread. To view this thread in it's original format and/or if you want to reply to this thread please [click here]

 

Author map
GrkEngineer

2005-08-30, 7:03 pm

I'm currently trying to implement a map<DWORD,cTexture> container. cTexture
is a class which I've created. I'm currently getting a degub assertion failed
error with an Expression: _BLOCK_TYPE_IS_VALID(pHead->nBlockUse). This shows
up when I first try to use the container. Why am I getting this error? Please
help.

Nicholas Nezis
Arnaud Debaene

2005-08-30, 7:03 pm

GrkEngineer wrote:
> I'm currently trying to implement a map<DWORD,cTexture> container.
> cTexture is a class which I've created. I'm currently getting a degub
> assertion failed error with an Expression:
> _BLOCK_TYPE_IS_VALID(pHead->nBlockUse). This shows up when I first
> try to use the container. Why am I getting this error? Please help.


Does your cTexture class holds any dynamically allocated memory? If yes,
make sure the copy constructor and operator= are correctly defined for the
class.

Arnaud
MVP - VC


GrkEngineer

2005-08-30, 7:03 pm

I created a work around my removing the dynamic allocation, but I would still
like to understand this. My copy constructor is

cTexture(const cTexture& obj) {*this = obj;}

Is this all I need? Also I'm not using the operator=. Is this always
necessary and how do I implement that? I appreciate your help.

Nick

"Arnaud Debaene" wrote:

> GrkEngineer wrote:
>
> Does your cTexture class holds any dynamically allocated memory? If yes,
> make sure the copy constructor and operator= are correctly defined for the
> class.
>
> Arnaud
> MVP - VC
>
>
>

Arnaud Debaene

2005-08-30, 7:03 pm

PS : Please don't top-post...

GrkEngineer wrote:
> I created a work around my removing the dynamic allocation, but I
> would still like to understand this. My copy constructor is
>
> cTexture(const cTexture& obj) {*this = obj;}
>
> Is this all I need?

No! If you haven't defined operator= for your class, you're stuck with the
default implementation of the compiler, which will be incorrect as soon as
the object contains a pointer. Beside, once there is no more memory (or any
other ressource) dynamically allocated in the object, the default copy
constructor and operator= generated by the compiler are perfectly fine...

> Also I'm not using the operator=. Is this always
> necessary and how do I implement that? I appreciate your help.

It's too long a subject to describe fully in a newsgroup. I refer you to
your favorite C++ teachbook. Basically, if you need to implement
copy-constructor, it's almost certain you need also to implement operator=
and destructor.

Basically, what is happening to you is the following :
class A
{
int* MyPointer;
public:
A : MyPointer(new int[10])
{}

~A()
{
delete [] MyPointer;
}

A(const A& other)
{
this->MyPointer=other.MyPointer;
}

A& operator=(const A& other)
{
this->MyPointer=other.MyPointer;
return *this
}
};

The copy constructor and operator= I've written are those generated by the
compiler if you don't write them yourself. Now, if you do :

A a1;
A a2(a1);
A a3=a1;

All instances (a1, a2, a3) share the same memory buffer pointed to by
MyPointer (new[] has been called only once). When those objects are
destroyrd (when they go out of scope), the first one to be destroyed free
this buffer in it's destructor. The 2 others try to free again the same,
already freed, buffer : that's what cause the assertion you get.

What you need is to write yourself copy constructor and operator=, something
like this :

A(const A& other)
{
MyPointer=new int[10];
memcpy(MyPointer, other.MyPointer, 10*sizeof(int));
}

A& operator=(const A& other)
{
delete[] MyPointer //release any previously allocated buffer
MyPointer=new int[10];
memcpy(MyPointer, other.MyPointer, 10*sizeof(int));
this->MyPointer=other.MyPointer;
return *this
}

This way, each object will have it's own copy of the buffer...
Since this bookkeeping can become boring ready fast (and is responsible for
countless bugs), there are tools and methods aimed at simplifying it :
Ressource Acquisition is Initialisation paradigm (RAII), smart pointers,
etc...

Arnaud
MVP - VC


Stephen Howe

2005-08-30, 9:57 pm

> My copy constructor is
>
> cTexture(const cTexture& obj) {*this = obj;}


I dont like this. The assigment operator, will treat the LHS as if it
exists, which it does not for copy constructor.
The LHS is a bald collection of bits, all arbitrary in content.
If the assigment operator did any operation like delete [] or free() on the
LHS before then assigning from RHS, you are in real trouble (BOOM! - corrupt
heap) as the LHS for the copy constructor is not valid. For a copy
constructor, you need to call the base classes copy constructor (if any base
class) using RHS as argument and then proceed to initalise each LHS member
in class order from equivalent RHS member.

> Is this all I need?


No

> Also I'm not using the operator=. Is this always
> necessary and how do I implement that?


It is _NOT_ necessary when
(i) the class consists of simple built-in types (e.g. int, long, double) -
the compiler generated version of operator= will assign the members of the
equivalent RHS member to the LHS member.
(ii) the class consists of class members that know how to assign
hemselves - (eg. std::string) - the compiler generated version of
operator= will call each members operator= in yoru class, in turn to assign
the RHS to the LHS.

It _IS_ necessary when you class is managing some type of resource - like a
pointer to memory.
The compiler generated version of operator= will just copy the pointer -
which is unlikely to be what you want.
When each object goes out of scope, the destructor is called, and presumably
delete [] or free() is called - and for the 2 objects - they will both point
to the same block of memory - and calling delete[] or free() twice on the
same block is a _MAJOR_ error - BOOM!!!

In general the "law of the big 3" applies here.
And that is if you find you _must_ have a destructor to "unmanage" some
resource, then you almost certainly need a copy constructor and assignment
operator (or alternatively you design your class so that it is not copy
constructible, not assignable).
"Law of the big 3": If you need one of destructor, copy constructor and
assignment operator - you need them all.
See
http://www.parashift.com/c++-faq-li....html#faq-27.10

For most of the STL, your classes must be copy constructible and assignable.

Stephen Howe


GrkEngineer

2005-08-30, 9:57 pm

Arnaud,

I can't begin to thank you for your thorough explanation. It was the most
informative reply that I have ever received. I definetly understand now.
Thank you.

Nick

Sponsored Links







Also available: Server administration forum archive | Web Design forum archive | Software forum archive | Hardware reviews archive

Copyright 2008 codecomments.com