"Debug Assertion Failed" On Smart Pointer

A

A_StClaire_

I read a section of my text on smart "counting" pointers and found it
confusing so I decided to get hands-on.

however I'm getting "Debug Assertion Failed... Expression:
_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)" whenever I run my code below.
program works fine after I bypass the msg.

any ideas? thx a lot.


#include "stdafx.h"

#using <mscorlib.dll>

using namespace std;

template <class T> class CountedPtr
{
public:

T* ptr;
long* count;

void dispose()
{
if((--(*count)) == 0)
{
delete count;
delete ptr;
}
}

explicit CountedPtr(T* p = 0) : ptr(p), count(new long(1))
{
}

CountedPtr(const CountedPtr <T>& p) throw() : ptr(p.ptr),
count(p.count)
{
++(*count);
}

~CountedPtr() throw()
{
dispose();
}

CountedPtr <T>& operator= (const CountedPtr <T>& p) throw()
{
if(this != &p)
{
dispose();
ptr = p.tr;
count = p.count;
++(*count);
}
return *this;
}

T& operator*() const throw()
{

return *ptr;
}

T* operator->() const throw()
{
return ptr;
}
};

int _tmain()
{
int i = 10;
int* sampleIntPtr = &i;

cout << *sampleIntPtr << "\n\n";

CountedPtr <int> countedIntPtr(sampleIntPtr);
CountedPtr <int> countedIntPtr2 = countedIntPtr;

cout << *countedIntPtr << "\n\n";
cout << *countedIntPtr2 << "\n\n";
cout << *(countedIntPtr.count) << "\n\n";
cout << *(countedIntPtr2.count) << "\n\n";

CountedPtr <int> countedIntPtr3 = countedIntPtr2;
CountedPtr <int> countedIntPtr4 = countedIntPtr2;

cout << *(countedIntPtr.count) << "\n\n";

return 0;
}
 
A

Alf P. Steinbach

* (e-mail address removed):
I read a section of my text on smart "counting" pointers and found it
confusing so I decided to get hands-on.

You read what you had written yourself, and got confused?

however I'm getting "Debug Assertion Failed... Expression:
_BLOCK_TYPE_IS_VALID(pHead->nBlockUse)" whenever I run my code below.
program works fine after I bypass the msg.

Most probably not (works fine, that is).

any ideas? thx a lot.


#include "stdafx.h"

This is not a standard header.

#using <mscorlib.dll>

This is a non-standard directive, a language extension for some compiler.

using namespace std;

template <class T> class CountedPtr
{
public:

T* ptr;
long* count;

Should not be public.

void dispose()
{
if((--(*count)) == 0)
{
delete count;
delete ptr;
}
}

Already you're in deep waters. 'dispose' allows the client code to invalidate
the 'count' and 'ptr' members, and then call 'dispose' again, bang crash.

Also, this kind of logic belongs in the destructor.

Leveraging constructors and destructors is what smart-pointers are all about,
implementation-wise, so that's what you should do if you're implementing a
smart-pointer.
 
A

A_StClaire_

Alf said:
* (e-mail address removed):

You read what you had written yourself, and got confused?

textbook.



This is not a standard header.



This is a non-standard directive, a language extension for some compiler.


using Visual Studio 2003 which automatically generated those.

Should not be public.

okay!



Already you're in deep waters. 'dispose' allows the client code to invalidate
the 'count' and 'ptr' members, and then call 'dispose' again, bang crash.

Also, this kind of logic belongs in the destructor.

Leveraging constructors and destructors is what smart-pointers are all about,
implementation-wise, so that's what you should do if you're implementing a
smart-pointer.


thx for shedding light on that.

I was just wondering if you could discuss the single argument
constructor:


explicit CountedPtr(T* p = 0) : ptr(p), count(new long(1))
{
}


namely, why is 'explicit' being used? why is the value zero being
assigned to the pointer argument? and what's with the ':'? it doesn't
look like inheritance has any relevance here.

thx again.
 
A

Alf P. Steinbach

* (e-mail address removed):
I was just wondering if you could discuss the single argument
constructor:

explicit CountedPtr(T* p = 0) : ptr(p), count(new long(1))
{
}


namely, why is 'explicit' being used?

It prevents automatic (implicit) conversion of a T* to a CountedPtr where a
CountedPtr is expected, but why the designed wanted that only s/he knows.

why is the value zero being assigned to the pointer argument?

That's a default value.

and what's with the ':'? it doesn't
look like inheritance has any relevance here.

That's a constructor initializer list; I think it's discussed in the FAQ.
 
M

Max M.

{
int i = 10;
int* sampleIntPtr = &i;

cout << *sampleIntPtr << "\n\n";

CountedPtr <int> countedIntPtr(sampleIntPtr);

Here you're binding a smart pointer to the address of a local automatic
variable. This makes no sense. Smart pointers serve the purpose of
automatically releasing dynamically allocated objects when they're no
longer needed. Your code, then, ends up with invoking 'delete' on a pointer
which hasn't been returned by 'new', which, of course, yields undefined
behaviour.

Max
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,755
Messages
2,569,535
Members
45,007
Latest member
obedient dusk

Latest Threads

Top