Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > C++ > newbie -- smart pointer destructor called without destructor everbeing called

Reply
Thread Tools

newbie -- smart pointer destructor called without destructor everbeing called

 
 
Jimmy Hartzell
Guest
Posts: n/a
 
      05-19-2008
I'm almost entirely new to C++, and so I assume I'm making a very common
blunder.

Context: I have an interpreted programming language with an interpreter
written in C (which works rather well), where we wanted to replace the
garbage collector we were using with one of our own, based off of
reference counting and cycle checking. After some experimentation, we
determined that it would be much more type-safe and easy-to-program in
if we moved the project over to C++ and used smart pointers to enforce
our invariants. Having little-to-know experience in C++, I decided to
experiment with reference-counting smart pointers and see if I could get
my own implementation to work.

I wrote a test program to test the implementation, and I got a
segmentation fault from my operating system. Inserting some debugging
code (the member variable "sentinal" and the "assert" statement), I
determined that it appears that, at some point, the software is
destructing a GCReference that it never constructed.

My implementation and test program follow:

#include <cassert>
#include <vector>

using namespace std;

class GCAllocation {
int refcount;

public:
void ref() {
__sync_fetch_and_add(&refcount,1);
}

void deref() {
assert(refcount!=0);
__sync_fetch_and_sub(&refcount,1);
if(!refcount) {
delete this;
}
}

GCAllocation() : refcount(0) {
refcount = 0;
}

virtual ~GCAllocation() {
}
};

template<class T>
class GCReference {
T *referand;
int sentinal;

void do_ref() {
if(referand) {
referand->ref();
}
}

void do_deref() {
do_deref(referand);
}

void do_deref(T *referand) {
if(referand) {
referand->deref();
}
}

public:
GCReference(T *const referand = 0) {
this->referand = referand;
sentinal = 3133;
do_ref();
}

GCReference(const GCReference<T> &ref) {
referand = ref.referand;
sentinal = 3133;
do_ref();
}

~GCReference() {
assert(sentinal==3133);
do_deref();
}

GCReference operator=(const GCReference<T>& ref) {
// not thread-safe
T* const old_ref = ref.referand;
referand = ref.referand;

// order necessary in case of self-assignment
do_ref();
do_deref(old_ref);
}

bool operator==(const GCReference<T>& ref) const {
return referand == ref.referand;
}

operator bool() const {
return referand;
}

T& operator*() const {
return *referand;
}

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

// not a cast, since that could be used by accident.
// this should only be used when absolutely necessary.
// TODO: find out how to support dynamic-casts without this
// sort of mechanism
T* get_raw_pointer() const {
return referand;
}
};

class GCTest: public virtual GCAllocation {
public:
vector<GCReference<GCTest> > refs;
GCTest() {
for(int i = 0; i < 16; ++i) {
refs.push_back(0);
}
}

void fill_all(GCReference<GCTest> what_with) {
for(int i = 0; i < 16; ++i) {
refs[i] = what_with;
}
}
};

static void test() {
GCReference<GCTest> test1(new GCTest());
GCReference<GCTest> test2(new GCTest());
test1->fill_all(test2);
test1->fill_all(0);
test1->fill_all(test2);
test1->fill_all(0);
assert(!test1->refs[5]);
test1->fill_all(test2);
assert(test1->refs[5] == test2);
}

int main() {
while(1) {
test();
}
return 0;
}

I get the following output:
$ c++ simple.c++
$ ./a.out
a.out: simple.c++:65: GCReference<T>::~GCReference() [with T = GCTest]:
Assertion `sentinal==3133' failed.
$ c++ --versionc++ (GCC) 4.1.3 20070929 (prerelease) (Ubuntu
4.1.2-16ubuntu2)
Copyright (C) 2006 Free Software Foundation, Inc.
This is free software; see the source for copying conditions. There is NO
warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.

$
 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Never ever use a raw pointer when a smart pointer can do the same job Hicham Mouline C++ 100 08-25-2009 05:07 PM
newbie -- smart pointer destructor called without destructor everbeing called Jimmy Hartzell C++ 2 05-20-2008 02:20 AM
Smart Pointer release() const : it can set the pointer to null with the keyword "const"? coala C++ 1 09-06-2006 03:00 PM
Smart Pointer release() const : it can set the pointer to null with the keyword "const"? coala C++ 3 09-06-2006 02:58 PM
Smart pointer without templates possible ? lothar.behrens@lollisoft.de C++ 0 04-29-2005 01:10 PM



Advertisments