[chuck-users] Passing classes to functions

Hans Aberg haberg at math.su.se
Fri Oct 2 14:16:53 EDT 2009


On 2 Oct 2009, at 09:38, Adam Tindale wrote:

> I was doing some work and created some bugs that I ironed out when I
> discovered something: when non-primitive types are passed to functions
> they are passed by reference and not by value! I include a test so you
> can see what I mean.
>
> I hope somebody find this useful.

Though it has been pointed out briefly as being the normal for a  
typical reference implementation, it might help to linger a bit on the  
details, and compare with the situation when a reference count or  
other GC (garbage collector) is present. - Some say chuck might get a  
ref count someday.

> class test{
> 0 => int val;
> }

Here, one typically implements two classes, this class test, and  
another (using pseudo-code)
   class test_ref {
     test* pointer_;
   };

If one uses a reference count, the class test will have an additional  
integer, hidden from public view, indicating how many copies there are:
   class test {
   private:
     int count_;
   public:
     0 => int val;
   }

> test obj1;

This produces the implementation:
   test_ref obj1;
   obj1.pointer_ = new test();
   obj1.count_ = 1;            // If reference count is used.

> // obj2 is a reference to obj1
> test obj2 @=> obj1;

Now, this is equivalent to the implementation:
   test_ref obj2;
   obj2.pointer_ = new test();     // By test obj2
   obj2.count_ = 1;                // If reference count is used.
   obj1.pointer_ = obj2.pointer_;  // By the @=>

Since chuck does not have a ref count, the original obj1.pointer_ now  
is referenced by nothing. So it is a memory leak. A so called tracing  
GC (garbage collector) can find this out by starting from the set of  
objects that originates all other objects: the function stack and  
global objects, which is called the root system, and follow all  
pointers. The objects not found in such a sweep are viewed as dead,  
and removed.

When using a reference count, one needs to check if obj1.pointer_ and  
obj2.pointer_ already point to the same object, and if they do, do  
nothing - assignment does not change anything. Otherwise decrease the  
reference count of obj1.pointer_, and if it becomes 0, remove it. Then  
increase the reference count of obj2.pointer_ and set obj1.pointer_ =  
obj2.pointer_.

> <<< obj1.val , "original object">>>;
> <<< obj2.val , "reference to original">>>;
>
> 2 => obj2.val;
>
> <<< obj1.val , "original object">>>;
> <<< obj2.val , "reference to original">>>;
>
> fun void testclasspassing(test i)
> {
>    <<< i.val, "in function" >>>;
> }

This will be implemented as
   void testclasspassing(test_ref i) {
     <<< i.pointer_->val, "in function" >>>;
   }

> testclasspassing(obj1);
> testclasspassing(obj2);

So this then becomes clear: obj1.pointer_ is the same as  
obj2.pointer_; therefore testclasspassing() prints the same object.  
(Since the pointer can be 0, then implementation might benefit from  
some check.)

There is a memory leak, that would have been prevented by the use of a  
reference count or other GC.

   Hans




More information about the chuck-users mailing list