"Debug Assertion Failed" On Smart Pointer

Discussion in 'C++' started by A_StClaire_@hotmail.com, Oct 6, 2005.

  1. Guest

    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;
    }
     
    , Oct 6, 2005
    #1
    1. Advertising

  2. * :
    > 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: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Oct 6, 2005
    #2
    1. Advertising

  3. Guest

    Alf P. Steinbach wrote:
    > * :
    > > 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?



    textbook.


    > > #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 Visual Studio 2003 which automatically generated those.


    > > using namespace std;
    > >
    > > template <class T> class CountedPtr
    > > {
    > > public:
    > >
    > > T* ptr;
    > > long* count;

    >
    > Should not be public.



    okay!


    > > 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.



    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.
     
    , Oct 6, 2005
    #3
  4. * :
    >
    > 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.

    --
    A: Because it messes up the order in which people normally read text.
    Q: Why is it such a bad thing?
    A: Top-posting.
    Q: What is the most annoying thing on usenet and in e-mail?
     
    Alf P. Steinbach, Oct 6, 2005
    #4
  5. Max M. Guest

    wrote:

    > {
    > 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
     
    Max M., Oct 6, 2005
    #5
    1. Advertising

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

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. SorceCode
    Replies:
    2
    Views:
    3,418
    Christian Janßen
    Jan 26, 2004
  2. Cormac
    Replies:
    3
    Views:
    2,623
    Kevin Goodsell
    Apr 6, 2004
  3. w3r3w0lf

    debug assertion failed

    w3r3w0lf, Apr 15, 2004, in forum: C++
    Replies:
    2
    Views:
    2,611
    John Harrison
    Apr 15, 2004
  4. Kapt. Boogschutter

    Debug Assertion Failed! and no obvious Error

    Kapt. Boogschutter, Jun 23, 2004, in forum: C++
    Replies:
    1
    Views:
    611
    red floyd
    Jun 23, 2004
  5. Arti Potnis
    Replies:
    2
    Views:
    6,782
    Howard
    Sep 2, 2004
Loading...

Share This Page