[comp.sys.mac.programmer] Problem in THINK C interface files for System 7.0a9?

dplatt@coherent.com (Dave Platt) (07/11/90)

I spent this evening chasing down an interesting bomb... other folks
might be affected by this, so beware!

Environment: System 6.0.5, Mac II, using THINK C 4.0.1 and the #include
files from the Big Bang CD-ROM (System 7.0a9).

Symptom: application bombs with an "odd address" error while processing
an O/S "resume" event.  The bomb occurs upon executing an RTS at the end
of the event-processing subroutine.  The bomb occurs only if the program
had posted a Notification Manager event while it was running in the
background.

Initial analysis: stack was malformed at the time of the RTS.
Commenting out various statements in the code pointed to the NMRemove()
call as the culprit.

Analysis via TMON: the MacTraps glue for the _NMInstall and _NMRemove
traps appears to follow the Pascal calling conventions, and pops the
argument of the call off of the stack before calling the traps.  The
code generated by THINK C for the NMInstall() and NMRemove() calls
follows C calling conventions, and adjusts the stack pointer by one
longword upon return.  This adjustment would normally have the effect of
removing the argument from the stack... but because the argument has
already been popped, the adjustment discards one longword of data from
the stack (my function's return address, in this case), and the world
implodes shortly thereafter.

Corrective measure:  edit the OsUtil.h #include file, add the "pascal"
keyword to the declarations for NMInstall and NMRemove, open the
MacHeaders.c file, precompile it, then re-make the affected project
files.

Side-note: I wondered why this problem caused a crash at NMRemove time,
and not at NMInstall time.  It turned out that my NMInstall call was
issued from within a C function that had some local variables;  the
compiler had reserved space for them with a LINK instruction, and issued
an UNLK just prior to the RTS.  The UNLK restores the stack pointer to
its correct value before the RTS occurs, discarding the incorrect stack
pointer left by the NMInstall call.  The misplaced stack pointer could
have caused other problems... local variables could have been
overwritten, for example... but in my case it did not.