This smart pointer doesnt protect against deletion of non-existing temporary memory!?

Even if all new statements are wrapped with smart pointers the following code ends with a memory crash. During execution temporaries are created and it seems to me they are part of the problem. At the crash the smart pointer trys to delete a temporary object that doesnt exist. Help is very much appreciated. Code follows here. The code tries to generalize muliplication to vectors.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
//FILE Source.cpp

#include "Test.h"
#include "SmartPointerVersion.h"
#include "Ptr.h"

using namespace TestSuite;

int main(){

	typedef Ptr<MC> Var;

	{
		Var s1 = new Scalar( 2 ) ;
	
		Var s2 = new Scalar( 3 ) ;

		Var s3 = new Scalar( 6 ) ; 	
		
		Var s4 = s1 * s2 ; 

		bool test = s4 == s3 ;
	}

}



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
//FILE SmartPointerVersion.h

#ifndef SMARTPOINTERVERSION_H
#define SMARTPOINTERVERSION_H

#include "Ptr.h"

class Scalar;
class Vector;


class MC{
public:
/* using multiple dispatch to find out what T MC represents in a multiplication */

virtual Ptr<MC> operator*( Ptr<MC>) =0;	/* unknownT__times__unknownT */
virtual Ptr<MC> T_x_S( Ptr<Scalar>) =0;	/* unknownT__times__Scalar */
virtual Ptr<MC> T_x_V( Ptr<Vector>) =0;	/* unknownT__times__Vector */
virtual bool operator==( Ptr<MC>) =0;	/* comparison unknownT with unknownT */

virtual ~MC(){}
};

class Vector;

class Scalar : public MC{
public:
	Scalar():scalar(0){}
	Scalar(double s):scalar(new double(s)){}
	Scalar( Scalar* s):scalar(new double(*(s->scalar))){}

	Ptr<MC> operator*( Ptr<MC> mc ){ 
		return mc->T_x_S( Ptr<Scalar>(this) ); 
	}
	Ptr<MC> T_x_S( Ptr<Scalar> s ){ 
		return S_x_S( this, s); 
	}
	Ptr<MC> T_x_V( Ptr<Vector> v ){ 
		return S_x_V( this, v); 
	}
	bool operator==( Ptr<MC> lhs ){ 
		return *(dynamic_cast<Scalar*>(&*lhs)->scalar) == *scalar;
	} /*hack to circumvent multiple dispatch orgie*/
	~Scalar(){/*missing memory management*/}
private:
	friend Ptr<MC> S_x_S( Ptr<Scalar> lhs, Ptr<Scalar> rhs);
	friend Ptr<MC> S_x_V( Ptr<Scalar> lhs, Ptr<Vector> rhs);
	Ptr<double>  scalar;
};




class Vector : public MC{
public:
	Vector(double s):vector1(new double (s)),vector2(new double (s)){}
	Vector(double elm1, double elm2 ):vector1(new double (elm1)),vector2(new double (elm2)){}
	Vector( Vector* mc):vector1(new double),vector2( new double ){ *vector1 = *mc->vector1; *vector2 = *mc->vector2;}
	
	Ptr<MC> operator*( Ptr<MC> mc ){ 
		return mc->T_x_V( this ); 
	}
	Ptr<MC> T_x_S( Ptr<Scalar> s ){ 
		return V_x_S( this, s ); 
	}
	Ptr<MC> T_x_V( Ptr<Vector> v ){ 
		return V_x_V( this, v ); 
	}
	bool operator==( Ptr<MC> rhs ){ return ( *(dynamic_cast<Vector*>( &*rhs )->vector1) == *vector1 )  &&  ( *(dynamic_cast<Vector*>( &*rhs )->vector2) == *vector2 );}
	~Vector(){/*missing memory management*/}
private:
	Ptr<double> vector1, vector2;
	friend Ptr<MC> V_x_S( Ptr<Vector>, Ptr<Scalar> );
	friend Ptr<MC> V_x_V( Ptr<Vector>, Ptr<Vector> );
	friend Ptr<MC> S_x_V( Ptr<Scalar>, Ptr<Vector> );
};

/* Operations */
Ptr<MC> S_x_S( Ptr<Scalar> lhs, Ptr<Scalar> rhs);
Ptr<MC> S_x_V(  Ptr<Scalar>  lhs,  Ptr<Vector> rhs);
Ptr<MC> V_x_S(  Ptr<Vector> lhs,  Ptr<Scalar> rhs);
Ptr<MC> V_x_V(  Ptr<Vector> lhs,  Ptr<Vector> rhs);
Ptr<MC> operator*( Ptr<MC>& lhs, Ptr<MC>& rhs );
bool operator==( Ptr<MC> lhs, Ptr<MC> rhs );


#endif SMARTPOINTERVERSION_H 



1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//FILE SmartPointerVersion.cpp

#ifndef SMARTPOINTERVERSION_CPP
#define SMARTPOINTERVERSION_CPP
#include "SmartPointerVersion.h"

/* Operations */
Ptr<MC> S_x_S( Ptr<Scalar> lhs, Ptr<Scalar> rhs){
	return Ptr<MC>(new Scalar(   *lhs->scalar *  *rhs->scalar   ));
} 

Ptr<MC> S_x_V(  Ptr<Scalar>  lhs,  Ptr<Vector> rhs){
	return Ptr<MC>(new Vector(   *(lhs->scalar) * *(rhs->vector1) , *(lhs->scalar) * *(rhs->vector2)   ));
} 

Ptr<MC> V_x_S(  Ptr<Vector> lhs,  Ptr<Scalar> rhs){
	return S_x_V( rhs, lhs );
} 

Ptr<MC> V_x_V(  Ptr<Vector> lhs,  Ptr<Vector> rhs){
	return Ptr<MC>(new Vector(  *lhs->vector1 * *rhs->vector1 , *lhs->vector2 * *rhs->vector2  ));
} 

Ptr<MC> operator*( Ptr<MC>& lhs, Ptr<MC>& rhs ){
	return *lhs * rhs;
}
bool operator==( Ptr<MC> lhs, Ptr<MC> rhs ){return *lhs == rhs;}


#endif SMARTPOINTERVERSION_CPP 




1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
//FILE Ptr.h 
// Smart Pointer (reference counted)

#ifndef GUARD_Ptr_h
#define GUARD_Ptr_h

#include <cstddef>
#include <stdexcept>

template <class T> class Ptr {
public:
	// new member to copy the object conditionally when needed
	void make_unique() {
		if (*refptr != 1) {
			--*refptr;
			refptr = new size_t(1);
			p = p? clone(p): 0;
		}
	}

	// the rest of the class looks like `Ref_handle' except for its name
	Ptr(): p(0), refptr(new size_t(1)) { }
	Ptr(T* t): p(t), refptr(new size_t(1)) { }
	Ptr(const Ptr& h): p(h.p), refptr(h.refptr) {
		++*refptr; 
	}

	Ptr& operator=(const Ptr&);    // implemented analogously to 14.2/261
	~Ptr();                        // implemented analogously to 14.2/262
	operator bool() const { return p; }
	T& operator*() const;          // implemented analogously to 14.2/261
	T* operator->() const;         // implemented analogously to 14.2/261

private:
	T* p;
#ifdef _MSC_VER
	size_t* refptr;
#else
	std::size_t* refptr;
#endif
};

template <class T> T* clone(const T* tp)
{
	return tp->clone();
}



template<class T>
T& Ptr<T>::operator*() const { if (p) return *p; throw std::runtime_error("unbound Ptr"); }

template<class T>
T* Ptr<T>::operator->() const { if (p) return p; throw std::runtime_error("unbound Ptr"); }


template<class T>
Ptr<T>& Ptr<T>::operator=(const Ptr& rhs)
{
        ++*rhs.refptr;
        // \f2free the lhs, destroying pointers if appropriate\fP
        if (--*refptr == 0) {
                delete refptr;
                delete p;
        }

        // \f2copy in values from the right-hand side\fP
        refptr = rhs.refptr;
        p = rhs.p;
        return *this;
}

template<class T> Ptr<T>::~Ptr()
{
        if (--*refptr == 0) {
                delete refptr;
                delete p;
        }
}


#endif 


Any help is highly appreciated.
Last edited on
Any help is highly appreciated.
1
2
3
Ptr<MC> operator*( Ptr<MC> mc ){ 
	return mc->T_x_S( Ptr<Scalar>(this) ); 
}

This will not work because other Ptr objects containing this will not share the same reference count.
Thanks! Very helpful comment!
Last edited on
Topic archived. No new replies allowed.