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.