Yuen Kwee wrote:

i was playing with internal alarm and had many problems with it,
cause i does not allow globals. i was just wondering
whether StrCopy() is a global call? i got and error like
    :
    :
pose error message:
InternalAlarm(1.0) just read from memory location 0x8003AFD2.
This access usually means that the application accessed a global
variable adter PilotMain was called with a launch code that does
not support globals. The last launch code sent to the application
was "sysAppLaunchCmdDisplayAlarm"
    :
    :
Char * CInternalAlarmData::GetName()
{
        static Char l_strName[100];

        StrCopy(l_strName,m_strName);

        return l_strName;
}

The problem is the "static" keyword.

When you put "static" on a local variable, it changes the
variable to use the same storage as globals use.  The
only difference between a static local variable and a
global is the scope that the *name* of the variable is
available in.  In other words, though you can't refer
to the l_strName variable by name outside the GetName()
function, the variable still does exist, and it lives with
the globals.

Furthermore, if the variable did NOT still exist after
the function returned, it would be an error to return a
pointer to the variable's storage, which exactly what you
do at the end of the function (with "return l_strName").

The solution to this problem is tricky.  You can't just
remove the "static" keyword.  That will place the buffer
in the stack, but the storage for the variable will no
longer be valid when you return from the function, so
you cannot do "return l_strName" -- doing that would
return a pointer to storage that isn't valid anymore.

Instead, you probably need to allocate the storage for
the result from the dynamic heap, return it to the caller,
and let the caller deallocate it.  Like this:

        Char * CInternalAlarmData::GetName()
        {
            Char *namecopy;

            namecopy = (Char *) MemPtrNew (1 + StrLen (m_strName));
            if (namecopy != NULL) { StrCopy (namecopy, m_strName)); }
            return namecopy;
        }

The caller would call GetName(), then do whatever it wishes with
that string, then call MemPtrFree() on it.  If you'd like, to
make the implementation cleaner, you could supply another method
(maybe called DiscardName()) that would do the MemPtrFree() for
the client of the class, so that the client doesn't have to be
aware of the implementation detail that the string is in the
storage heap and that MemPtrNew() is the proper way to free it.

Another option is to just let the caller do the work of allocating
the buffer:

        Int32 CInternalAlarmData::GetNameLength()
        {
            return (StrLen (m_strName));
        }

        void CInternalAlarmData::GetName (Char *buffer)
        {
            if (buffer != NULL) { StrCopy (buffer, m_strName); }
        }

        void foo ()
        {
            CInternalAlarmData alarmdata (whatever);
            Char *namebuf;

            namebuf = (Char *) MemPtrNew (1 + alarmdata.GetNameLength());
            if (namebuf != NULL)
            {
                alarmdata.GetName (namebuf);
            }
        }

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