[comp.sys.mac.programmer] MPW C 2.0.2 bug suspected, how do I localize it?

freeman@spar.SPAR.SLB.COM (Jay Freeman) (06/14/88)

I have a possible bug in MPW C 2.0.2, that is sufficiently subtle that I am
having great difficulty localizing it well enough to report neatly; I seek
advice on how best to do so.

I am running on a Mac II with finder 6.0, system 4.2, compiling C with the
"-g" flag set but with no other compile options.

In a large, messy function (which I will call "foo") I have a declaration
like this:

	long myLong;

In "foo", "myLong" is initialized to a value.  Subsequently, "foo" calls
"bar", and "bar" calls "SFGetFile".  "myLong" is entirely local to "foo";
before I started putting in "printf" statements to debug, neither "myLong"
nor its address were passed to any other function or assigned to any extern
or static variable; in particular they are NOT passed to "bar".

Something was wrong with "foo", and in due course I found that the value of
"myLong" changed mysteriously during the call of "bar".  That is, I
"printf"ed out "myLong" immediately before and immediately after the call of
"bar", and got different values.  On fiddling around inside "bar", I found
that commenting out the call to "SFGetFile" made the problem go away.  I
don't know much about the internals of "SFGetFile", so I couldn't follow
that lead.  So I restored the call of "SFGetFile".

Gosh, I thought, maybe I am messing up the toolbox-calling syntax somehow,
so that something is scrambling the stack.  To test for that possibility,
I bracketed the declaration of "myLong" with dummy declarations of big
arrays on the stack, like this:

	char dummy1[ 500 ];
	long myLong;
        char dummy2[ 500 ];

Notwithstanding these arrays, the mysterious change in "myLong" persisted.
That's pretty convincing evidence that the culprit is not run-of-the-mill
stack-scrambling.  So I took out the dummy declarations.

Gosh, I thought, maybe there's a problem with register saves and restores.
I know that MPW C tries hard to put automatics in register, but there is no
easy way to find out which ones.  First I changed the declaration of
"myLong" to look like this:

	register long myLong:

There was no change in the bug.  Perhaps "myLong" was being put into a
register anyway.  So I restored the declaration of "myLong" to its original
form, and added to "foo" a call to a bogus function:

	bogus( &myLong );

where "bogus" is a void function that ignores all its arguments and
immediately returns:

	void bogus() {;}

The idea here is that the MPW C manual indicates that taking the address of
an automatic will prevent the compiler from automagically making it a
"register" variable.

WITH THE CALL TO "bogus" INSTALLED, THE BUG WENT AWAY!

I now have a strong feeling that the code generated for the original version
of "foo" put "myLong" in a register that was not saved across the call to
"bar", and that "SFGetFile" uses that register.  But I am not at all sure
how to proceed to localize the problem further.  "foo" is about 50-100 lines
of code with about 10 locals; "bar" is about half as complex.  Both of these
functions are in turn pretty well out to the leaves of the call graph of a
program that presently has something like 20,000 lines of C.  The only
debugger/disassembler I have is Macsbug, I have in essence never used it at
all, and I am not particularly a 68XXX assembly-language programmer anyway.

If there is indeed a problem with register saves, it would be a very serious
compiler bug, well worth tracking down and reporting.  (On the other hand,
if I am indeed making some unrecognized stupid C programming error, I will
feel very seriously foolish.)

Does anyone on the net -- in particular, any Apple net-watcher -- have any
suggestions as to what I should do next in order to localize and report the
bug.  I'm not asking for a work-around, the business with "bogus" already
provides that.  I'd just like to nail this one so it will get fixed in the
future.

						-- Jay Freeman

<canonical disclaimer; these are my opinions only>

gz@spt.entity.com (Gail Zacharias) (06/14/88)

In article <1215@spar.SPAR.SLB.COM> freeman@spar.UUCP (Jay Freeman) writes:
>I have a possible bug in MPW C 2.0.2, that is sufficiently subtle that I am
>having great difficulty localizing it well enough to report neatly; I seek
>advice on how best to do so.
> ....		   So I restored the declaration of "myLong" to its original
>form, and added to "foo" a call to a bogus function:
>	bogus( &myLong );
>WITH THE CALL TO "bogus" INSTALLED, THE BUG WENT AWAY!

Sounds like you've localized it.  Now just disassemble (i.e. dumpobj) "foo"
both with and without the call to "bogus" and take a good look at the code
generated.

(I won't even mention the relevance of this kind of situation to a certain
other discussion taking place in this group...)

--
gz@entity.com					...!mit-eddie!spt!gz
	 Now let's all repeat the non-conformist oath.

earleh@eleazar.dartmouth.edu (Earle R. Horton) (06/14/88)

In article <1215@spar.SPAR.SLB.COM> freeman@spar.UUCP (Jay Freeman) writes:
>
>I now have a strong feeling that the code generated for the original version
>of "foo" put "myLong" in a register that was not saved across the call to
>"bar", and that "SFGetFile" uses that register.

This is a wild guess, but do you perchance have an INIT named
"QuickFolder" or something in your system folder?  I ran into exactly
this problem, and finally found out QuickFolder was using D2, and not
restoring it.  This is a general problem with Pascal on the Mac:
Pascal functions and procedures do not save exactly the same registers
as C expects, or as the ToolBox does in many cases.  I believe the
problem with QuickFolder was that it had a Pascal procedure in it
which was patching itself into SFxxxFile somewhere, and the Pascal
compiler was not saving the same regs as the Package routine was.
This is not the fault of the Pascal compiler, either, since how can it
possibly know that it is generating code which will be put in a patch?
Another possibility (Heaven forbid!) is that the INIT was written in
assembly, and the author simply didn't save the correct registers.

I don't think this is a problem with MPW C, I really think you have a
defective INIT.  I call SFGetFile() all the time from MPW C functions
which have scads of auto variables, and never had any problem except
for the QuickFolder thing.



*********************************************************************
*Earle R. Horton, H.B. 8000, Dartmouth College, Hanover, NH 03755   *
*********************************************************************

freeman@spar.SPAR.SLB.COM (Jay Freeman) (06/16/88)

I am Jay Freeman, the original poster of the bug report.

In article <8886@dartvax.Dartmouth.EDU> earleh@eleazar.dartmouth.edu (Earle
R.  Horton) writes:

>This is a wild guess, but do you perchance have an INIT named
>"QuickFolder" or something in your system folder?
>
>	[technical discussion follows]
>
>*********************************************************************
>*Earle R. Horton, H.B. 8000, Dartmouth College, Hanover, NH 03755   *
>*********************************************************************

Thanks, Earle, you were right.  I was using "QuickFolder".  Removing it
made the suspicious code run correctly in its original, un-work-arounded
form.

I take back all those nasty thoughts I was beginning to have about MPW C.
(Who knows, perhaps I will have need of them in the future ..)

Sheesh -- with bugs like this around, why are people worrying about viruses?


						-- Jay Freeman

<canonical disclaimer: these words are my personal opinions>