JAMES S HAINES wrote:
I'm having trouble figuring out how to return
a handle or pointer from a function.  Is the
only alternative to make all such handles global?
The function below attempts to return a local
handle. This seems to work but may be causing
some of my crashes later in the program.

MemHandle getFieldText(UInt16 fieldID)
{
        FieldType*              fldP;
        MemHandle               h;
        char*                   fieldTextP;

        fldP=getObjectPtr(fieldID);     //get a pointer to the field
        h = FldGetTextHandle(fldP);
        if(h)
        {
                fieldTextP = MemHandleLock(h);  // prevent the chunk from 
moving (lock) and obtain pointer to location
                if(fieldTextP)
                        MemHandleResize(h, StrLen(fieldTextP)+1);
                MemHandleUnlock(h);
        }
return h;


There is no problem returning a MemHandle from a function.  It's just
an integer value, like a pointer or an int.

However, there is a problem in your code.  Well, two problems.  Well,
perhaps three or zero or one, depending on how you look at it.

The first is that you don't check whether MemHandleResize() succeeds;
you should always do that because it will fail if there isn't a chunk
available that's big enough, and it will also fail for another reason.

The second is that you lock the handle before passing it to
MemHandleResize().  Sometimes MemHandleResize() needs to move the
memory that the handle refers to to a new location if the memory
needs to be grown and there isn't space to do that at the current
location.  But it cannot do that if it is locked, because the purpose
of locking a handle is to make it immovable!

The third problem, which kind of makes the others moot, is that you
don't need to call MemHandleResize() in the first place.  If the handle
is owned by a field, then the field will always ensure that the memory
the handle refers to is big enough for the text.  So, by checking the
length of the text and then resizing the handle, you're really doing
what probably amounts to a no-op, because the handle is already big
enough for the text.  (If it weren't, then when processing events for
the field, the system would be writing past the end of the allocated
memory, and hopefully the system doesn't do that.)

But, let's think for another second about whether that really is a no-op.
What if your MemHandleResize() decreases the size of the handle?  This
could actually happen if some text is deleted from the field, and then
you go and make it exactly the right size with your function.  And what
if the system has code that caches the size of the handle, and doing
the MemHandleResize() doesn't update that information?  Then, suppose
the field had 10 characters in it, but then it's reduced to 5 characters,
and then you do MemHandleResize() and make the handle 6 bytes in size,
and then someone enters some text in the field.  Is the system going to
know that the handle is no longer big enough to hold 10 characters?
If it doesn't, it's going to overwrite memory.  I'm not saying this
WILL happen or even can happen (the system's field code might call
MemHandleSize() every time it needs to know the handle size), but I
can't prove that it won't, so personally I wouldn't risk it.

Personally, I play it safe and only ever do 2 things with a field's
handle:

1.  FldGetTextHandle(), then lock it, read the text (possibly make a
    copy), then immediately unlock it.
2.  FldSetTextHandle() to some handle that has no locks, and then
    in my own code forget the handle I just assigned so that I don't
    use it later.

Hope that helps.

  - Logan

--
For information on using the PalmSource Developer Forums, or to unsubscribe, 
please see http://www.palmos.com/dev/support/forums/

Reply via email to