[comp.sys.mac.programmer] Think C Objects in motion???

wlj1@cunixb.cc.columbia.edu (Wayne L Jebian) (09/14/90)

I've noticed some strange behavior from the TCL.

Sometimes when I execute a toolbox call from within a method, I get the 
ubiquitous odd address error. This had me _REALLY CONFUSED_ until I
tried putting the offending calls in other places: that is,
in glue that put the trap calls outside the object's struct.

Well, now my code doesn't break but I'm still confused. Is code (the methods)
being moved around without updating the PC? I thought that the objects could
be treated transparently as pointers - i.e. no locking required.

The problem is not severe, but I like to avoid kludges whenever possible. Has
anyone else experienced this, and if so, do you know why??

(c++)--

-Wayne
Send Mail to: jtt@paradox.psych.columbia.edu

beard@ux5.lbl.gov (Patrick C Beard) (09/16/90)

In article <1990Sep14.105646.23614@cunixf.cc.columbia.edu> wlj1@cunixb.cc.columbia.edu (Wayne L Jebian) writes:
#
#I've noticed some strange behavior from the TCL.
#
#Sometimes when I execute a toolbox call from within a method, I get the 
#ubiquitous odd address error. This had me _REALLY CONFUSED_ until I
#tried putting the offending calls in other places: that is,
#in glue that put the trap calls outside the object's struct.

This last sentence doesn't make any sense, really, I assume you meant that
you can fix it if you call the toolbox outside of an object's method.

#Well, now my code doesn't break but I'm still confused. Is code (the methods)
#being moved around without updating the PC? I thought that the objects could
#be treated transparently as pointers - i.e. no locking required.

1.  The code/method of an object is just regular C code, and therefore it
won't move unless you specifically mark the segment purgeable.

2.  Objects are handles, not pointers, and therefore have to be treated with
kindness.  The rule is, don't assign into an object's fields if the rhs of
the assignment can move memory.  For example:

struct MyObject {
/* methods. */
	void IMyObject();

/* data. */
	Handle itsData;
};

void MyObject::IMyObject()
{
	itsData = NewHandle(1024);	/* dangerous, NewHandle moves memory */
	{
		Handle temp = NewHandle(1024);
		itsData = temp;
	}
}

The first assignment is dangerous, the second is safe.  I'm guessing that
this is the problem you were experiencing.  Alternatively, you can lock your
object:

void MyObject::Lock()
{
	HLock((Handle)this);
}

Use this method when you are about to do something dangerous like the
above assignment.  However, using temporary variables is actually faster,
because you can avoid all those implicit double dereferences.


--
-------------------------------------------------------------------------------
-  Patrick Beard, Macintosh Programmer                        (beard@lbl.gov) -
-  Berkeley Systems, Inc.  ".......<dead air>.......Good day!" - Paul Harvey  -
-------------------------------------------------------------------------------

egw%weaks@lanl.gov (Eric Wasserman) (09/18/90)

In article <6988@dog.ee.lbl.gov> beard@ux5.lbl.gov (Patrick C Beard) 
writes:

With regard to objects in Think C:

> 2.  Objects are handles, not pointers, and therefore have to be treated
> with kindness.  The rule is, don't assign into an object's fields if
> the rhs of the assignment can move memory.

Actually this is not the case in which instance variables are a problem.  
Page 192 of the Think C manual states:  "It is OK to assign values to
instance variables, even when the expression on the right hand side may
move memory."  In Think C the rhs is evaluated first (including any 
memory shuffling) and THEN the handle reference on the lhs is evaluated.

The real problem is passing the address of an instance variable to a
routine which may move memory.  There is an example of this in the same
page in the Think C manual.

I hope this helps.

Eric Wasserman

phils@chaos.cs.brandeis.edu (Phil Shapiro) (09/18/90)

In article <63234@lanl.gov> egw%weaks@lanl.gov (Eric Wasserman) writes:

>   In article <6988@dog.ee.lbl.gov> beard@ux5.lbl.gov (Patrick C Beard) 
>   writes:
>
>   With regard to objects in Think C:
>
>   > 2.  Objects are handles, not pointers, and therefore have to be treated
>   > with kindness.  The rule is, don't assign into an object's fields if
>   > the rhs of the assignment can move memory.
>
>   Actually this is not the case in which instance variables are a problem.  
>   Page 192 of the Think C manual states:  "It is OK to assign values to
>   instance variables, even when the expression on the right hand side may
>   move memory."  In Think C the rhs is evaluated first (including any 
>   memory shuffling) and THEN the handle reference on the lhs is evaluated.

Yes, it is OK to assign any expression to an instance variable inside
any method for the object contains that instance variable.  In
general, you CANNOT depend on ThC completely evaluating the rhs of "="
before the lhs.  Assignment to an object's instance variable within
that object's method is a special case.  For example:

void myobj::Crash()
{
    ivar = MoveMemory();              /* OK to do */
    otherobj->ivar = MoveMemory();    /* not OK */
    (**myHandle).ivar = MoveMemory(); /* not OK */
}

>   The real problem is passing the address of an instance variable to a
>   routine which may move memory.  There is an example of this in the same
>   page in the Think C manual.

Also, watch out for passing the address of an instance variable along
with a function that may move or purge memory.  For example:

void myobj::Crash2()
{
    /* assume OtherFunc doesn't move memory */
    OtherFunc(&ivar, MoveMemory());  /* not OK, ivar may relocate before use */
}

>   I hope this helps.
>
>   Eric Wasserman

    Me too!

	-phil shapiro, symantec tech support
--
Phil Shapiro
phils@chaos.cs.brandeis.edu

francis@magrathea.uchicago.edu (Francis Stracke) (09/25/90)

In article <1990Sep14.105646.23614@cunixf.cc.columbia.edu> wlj1@cunixb.cc.columbia.edu (Wayne L Jebian) writes:
>
>I've noticed some strange behavior from the TCL.
>
>Sometimes when I execute a toolbox call from within a method, I get the 
>ubiquitous odd address error. This had me _REALLY CONFUSED_ until I
>tried putting the offending calls in other places: that is,
>in glue that put the trap calls outside the object's struct.
>
>Well, now my code doesn't break but I'm still confused. Is code (the methods)
>being moved around without updating the PC? I thought that the objects could
>be treated transparently as pointers - i.e. no locking required.

I do know that Think Pascal uses handles instead of pointers to reference the
objects--but only their data should be in the block referenced.  The code
should be in the CODE resources like any other.  The object's block of RAM
just holds pointers (or something) to tell what routines to call.