[comp.sys.mac.programmer] Speaking of Munger...

pepke@gw.scri.fsu.edu (Eric Pepke) (07/11/90)

Speaking of Munger, it's a cute little routine, but what happens when it 
fails due to insufficient memory?

I run this little test program: 

#include <stdio.h>
#include <MacTypes.h>
#include <MemoryMgr.h>

main()
{
    unsigned char buffer[1000];
    Handle block;
    long beforeLength, afterLength;
    
    printf("Yahoo!\n");
    
    block = NewHandle(0L);
        
    for (;;)
    {
        beforeLength = GetHandleSize(block);
        Munger(block, GetHandleSize(block), (unsigned char *) 0, 
                0L, buffer, (long) sizeof(buffer));
        afterLength = GetHandleSize(block);
        
        if (beforeLength + sizeof(buffer) > afterLength || MemError())
        {
            printf("\nSize increased from %ld to %ld\n", 
                    beforeLength, afterLength);
            printf("MemError() == %d\n", MemError());
            exit(-1);
        }
        else
        {
            printf(".");
        }
    }
}

and I get

Yahoo!
...........................................................................
.....
...........................................................................
.....
...........................................................................
.....
.......................................................................
Size increased from 311000 to 311000
MemError() == 0

So, when Munger fails due to lack of memory, you cannot tell from looking 
at MemError.  In this case, at least, it left the handle unchanged.  Can 
somebody who knows about the internals of Munger tell me if that is 
guaranteed to be the case, or is there a possibility that the handle will 
be corrupted in any way, such as being left larger than it was but not as 
large as is needed?

Eric Pepke                                    INTERNET: pepke@gw.scri.fsu.edu
Supercomputer Computations Research Institute MFENET:   pepke@fsu
Florida State University                      SPAN:     scri::pepke
Tallahassee, FL 32306-4052                    BITNET:   pepke@fsu

Disclaimer: My employers seldom even LISTEN to my opinions.
Meta-disclaimer: Any society that needs disclaimers has too many lawyers.

keith@Apple.COM (Keith Rollin) (07/13/90)

In article <233@sun13.scri.fsu.edu> pepke@gw.scri.fsu.edu (Eric Pepke) writes:
>Speaking of Munger, it's a cute little routine, but what happens when it 
>fails due to insufficient memory?
>
>I run this little test program: 
>
>#include <stdio.h>
>#include <MacTypes.h>
>#include <MemoryMgr.h>
>
>main()
>{
>    unsigned char buffer[1000];
>    Handle block;
>    long beforeLength, afterLength;
>    
>    printf("Yahoo!\n");
>    
>    block = NewHandle(0L);
>        
>    for (;;)
>    {
>        beforeLength = GetHandleSize(block);
>        Munger(block, GetHandleSize(block), (unsigned char *) 0, 
>                0L, buffer, (long) sizeof(buffer));
>        afterLength = GetHandleSize(block);
>        
>        if (beforeLength + sizeof(buffer) > afterLength || MemError())
>        {
>            printf("\nSize increased from %ld to %ld\n", 
>                    beforeLength, afterLength);
>            printf("MemError() == %d\n", MemError());
>            exit(-1);
>        }
>        else
>        {
>            printf(".");
>        }
>    }
>}
>
>and I get
>
>Yahoo!
>...........................................................................
>.....
>...........................................................................
>.....
>...........................................................................
>.....
>.......................................................................
>Size increased from 311000 to 311000
>MemError() == 0
>
>So, when Munger fails due to lack of memory, you cannot tell from looking 
>at MemError.  In this case, at least, it left the handle unchanged.  Can 
>somebody who knows about the internals of Munger tell me if that is 
>guaranteed to be the case, or is there a possibility that the handle will 
>be corrupted in any way, such as being left larger than it was but not as 
>large as is needed?

When Munger needs some more memory, it calls SetHandleSize. If
SetHandleSize returns an error (returned in register D0), Munger exits
immediately. This means that the error result code is still in D0, and
you can retrieve it with a little bit of glue code or inline assembly.

The reason why MemError isn't set is because the Memory Manager doesn't
set it; that's the function of the glue code provided for those calls
by your development system. Your call to something like SetHandleSize
is really a call to subroutine that takes your parameters off the stack,
puts them in registers, calls the function, and puts the result code in
MemError.  Since Munger is written in assembly, it doesn't use this
little subroutine.  Hence, MemError never gets set with the result
code.

I've heard that there will be an article on this in an upcoming issue
of d e v e l o p.

-- 
------------------------------------------------------------------------------
Keith Rollin  ---  Apple Computer, Inc.  ---  Developer Technical Support
INTERNET: keith@apple.com
    UUCP: {decwrl, hoptoad, nsc, sun, amdahl}!apple!keith
"Argue for your Apple, and sure enough, it's yours" - Keith Rollin, Contusions

russotto@eng.umd.edu (Matthew T. Russotto) (07/13/90)

In article <42917@apple.Apple.COM> keith@Apple.COM (Keith Rollin) writes:
>When Munger needs some more memory, it calls SetHandleSize. If
>SetHandleSize returns an error (returned in register D0), Munger exits
>immediately. This means that the error result code is still in D0, and
>you can retrieve it with a little bit of glue code or inline assembly.
>
>The reason why MemError isn't set is because the Memory Manager doesn't
>set it; that's the function of the glue code provided for those calls
>by your development system. Your call to something like SetHandleSize
>is really a call to subroutine that takes your parameters off the stack,
>puts them in registers, calls the function, and puts the result code in
>MemError.  Since Munger is written in assembly, it doesn't use this
>little subroutine.  Hence, MemError never gets set with the result
>code.

Says Inside Mac, Volume 4:
All Memory Manager routines (including the RecoverHandle function) return a
result code that you can examine by calling the MemError function.

And a look at the SetHandleSize function reveals that it does indeed move
D0 to MemErr... Hmmmm.  (Unless, of course, you are running under the 64K
Roms)
--
Matthew T. Russotto	russotto@eng.umd.edu	russotto@wam.umd.edu
][, ][+, ///, ///+, //e, //c, IIGS, //c+ --- Any questions?
		Hey!  Bush has NO LIPS!

russotto@eng.umd.edu (Matthew T. Russotto) (07/13/90)

In article <42917@apple.Apple.COM> keith@Apple.COM (Keith Rollin) writes:
>In article <233@sun13.scri.fsu.edu> pepke@gw.scri.fsu.edu (Eric Pepke) writes:
>>Speaking of Munger, it's a cute little routine, but what happens when it 
>>fails due to insufficient memory?
>>
>>I run this little test program: 
>>
>>#include <stdio.h>
>>#include <MacTypes.h>
>>#include <MemoryMgr.h>
>>
>>main()
>>{
>>    unsigned char buffer[1000];
>>    Handle block;
>>    long beforeLength, afterLength;
>>    
>>    printf("Yahoo!\n");
>>    
>>    block = NewHandle(0L);
>>        
>>    for (;;)
>>    {
>>        beforeLength = GetHandleSize(block);
>>        Munger(block, GetHandleSize(block), (unsigned char *) 0, 
>>                0L, buffer, (long) sizeof(buffer));
>>        afterLength = GetHandleSize(block);
>>        
>>        if (beforeLength + sizeof(buffer) > afterLength || MemError())
>>        {
>>            printf("\nSize increased from %ld to %ld\n", 
>>                    beforeLength, afterLength);
>>            printf("MemError() == %d\n", MemError());
>>            exit(-1);
>>        }
>>        else
>>        {
>>            printf(".");
>>        }
>>    }
>>}
>>
>>and I get
>>
>>Yahoo!
>>...........................................................................
>>.....
>>...........................................................................
>>.....
>>...........................................................................
>>.....
>>.......................................................................
>>Size increased from 311000 to 311000
>>MemError() == 0
>>
>>So, when Munger fails due to lack of memory, you cannot tell from looking 
>>at MemError.  In this case, at least, it left the handle unchanged.  Can 
>>somebody who knows about the internals of Munger tell me if that is 
>>guaranteed to be the case, or is there a possibility that the handle will 
>>be corrupted in any way, such as being left larger than it was but not as 
>>large as is needed?
>
> [detailed, but, except on the 64K ROMs, incorrect explanation...Sorry Keith]

The real reason your MemError() test is failing is that printf uses the memory
manager, and that clears MemErr (because the calls printf makes succeed)
--
Matthew T. Russotto	russotto@eng.umd.edu	russotto@wam.umd.edu
][, ][+, ///, ///+, //e, //c, IIGS, //c+ --- Any questions?
		Hey!  Bush has NO LIPS!

pepke@gw.scri.fsu.edu (Eric Pepke) (07/14/90)

In article <1990Jul13.142801.6843@eng.umd.edu> russotto@eng.umd.edu 
(Matthew T. Russotto) writes:
> The real reason your MemError() test is failing is that printf uses the 
memory
> manager, and that clears MemErr (because the calls printf makes succeed)

No.  C evaluates the operands to printf before it invokes it.

However, you are partially correct in that it was my error.  It's not the 
printf call that resets MemErr; it's the GetHandleSize.  If I put the 
return value of MemError into a variable before calling that, it returns 
-108, which is exactly what I had hoped.

Eric Pepke                                    INTERNET: pepke@gw.scri.fsu.edu
Supercomputer Computations Research Institute MFENET:   pepke@fsu
Florida State University                      SPAN:     scri::pepke
Tallahassee, FL 32306-4052                    BITNET:   pepke@fsu

Disclaimer: My employers seldom even LISTEN to my opinions.
Meta-disclaimer: Any society that needs disclaimers has too many lawyers.

keith@Apple.COM (Keith Rollin) (07/16/90)

In article <1990Jul13.135946.6664@eng.umd.edu> russotto@eng.umd.edu (Matthew T. Russotto) writes:
>In article <42917@apple.Apple.COM> keith@Apple.COM (Keith Rollin) writes:
>>When Munger needs some more memory, it calls SetHandleSize. If
>>SetHandleSize returns an error (returned in register D0), Munger exits
>>immediately. This means that the error result code is still in D0, and
>>you can retrieve it with a little bit of glue code or inline assembly.
>>
>>The reason why MemError isn't set is because the Memory Manager doesn't
>>set it; that's the function of the glue code provided for those calls
>>by your development system. Your call to something like SetHandleSize
>>is really a call to subroutine that takes your parameters off the stack,
>>puts them in registers, calls the function, and puts the result code in
>>MemError.  Since Munger is written in assembly, it doesn't use this
>>little subroutine.  Hence, MemError never gets set with the result
>>code.
>
>Says Inside Mac, Volume 4:
>All Memory Manager routines (including the RecoverHandle function) return a
>result code that you can examine by calling the MemError function.
>
>And a look at the SetHandleSize function reveals that it does indeed move
>D0 to MemErr... Hmmmm.  (Unless, of course, you are running under the 64K
>Roms)

Sigh. Again, I've thrown a walk concerning Munger. Eric eventually found
the problem (he was making another Memory Manager call and erasing MemErr
from the Munger call). I had assumed that the Memory Manager didn't 
actually set MemErr because there was glue that also did it.

-- 
------------------------------------------------------------------------------
Keith Rollin  ---  Apple Computer, Inc.  ---  Developer Technical Support
INTERNET: keith@apple.com
    UUCP: {decwrl, hoptoad, nsc, sun, amdahl}!apple!keith
"Argue for your Apple, and sure enough, it's yours" - Keith Rollin, Contusions

oster@well.sf.ca.us (David Phillip Oster) (07/18/90)

One of my clients claims that Munger has bugs with offsets over 32k. I
haven't checked this out for myself.
-- 
-- David Phillip Oster - Note new address. Old one has gone Bye Bye.
-- oster@well.sf.ca.us = {backbone}!well!oster