Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to fix "malloc: can't protect region for postlude guard page" warnings on iOS

I'm developing an iOS app and when I run it on my devices I got lots of the following warnings:

MyApp(2138,0x104338000) malloc: *** can't protect(0x3) region for postlude guard page at 0x104950000

They don't stop the execution but looks scary and probably are related to occasional crash of my app. I googled and only found two pages on the entire web and none of the helps. I wonder if anyone here knows how to fix this?

Edit: here is the product scheme I used:

like image 625
ios learner Avatar asked Apr 22 '15 22:04

ios learner


2 Answers

The error you're seeing comes from Apple's malloc implementation and is due to vm_protect failing when trying modify memory protection of the guard pages that have been added to your memory allocations.

So it sounds like you've enabled debugmalloc's MallocGuardEdges flag (I didn't think debugmalloc was available on ios devices).

The 0x3 = VM_PROT_READ | VM_PROT_WRITE in the message is saying that vm_protect failed to make the page read-write which means that this is happening in response to a free.

The only documented return codes for vm_protect are KERN_PROTECTION_FAILURE and KERN_INVALID_ADDRESS so at this point I can only guess what happened. Making a page read-write seems like a modest request, for a valid page you wouldn't expect KERN_PROTECTION_FAILURE, which leaves KERN_INVALID_ADDRESS, meaning that perhaps your page at 0x104950000 is invalid.

Which would imply a memory stomping bug.

like image 136
Rhythmic Fistman Avatar answered Oct 07 '22 02:10

Rhythmic Fistman


The issue is one-year old, but we ran into the same issue and found this thread. We where able to simplify and reproduce it in latest Xcode 7.3 on Mac with the following piece of C code:

int main(int argc, char *argv[])
    {
    const int s = 100, n = 5000;
    int i;
    void *p = malloc(s);
    for (i = 2 ; i <= n ; i++)
        p = realloc(p,i * s);
    for (i = n - 1 ; i > 0 ; i--)
        {
        void *newp = realloc(p,i * s);
        if (newp != p)
            printf("realloc(p,%d * %d = %d) changes pointer from %p to %p\n",i,s,i * s,p,newp);
        p = newp;
        }
    free(p);
    return 0;
    }

This will trigger the malloc_printf() breakpoint in the 2nd for loop (when the reallocations shrink memory) and print:

malloc: *** can't protect(0x3) region for postlude guard page at 0x48ed000

It appears (setting a breakpoint on malloc_printf()) that this happens exactly on the first time that realloc() changes the returned pointer, the total output of above program is:

realloc(p,1249 * 100 = 124900) changes pointer from 0x48b0000 to 0x5000000
realloc(p,2 * 100 = 200) changes pointer from 0x5000000 to 0x240cc60

Playing a bit with combinations of the block size s and number of iterations n it happens at least for 10/50000, 100/5000, 200/5000, ..., it seems when the allocated memory i * s shrinks to around 124000 bytes. Other combinations like 1/200000 don't trigger malloc_printf().

Given the simplicity of this code snippet, we believe that this is a bug in Apple's malloc debug implementation.... or the message is supposed to be some informative (internal) message rather than trying to signal a real memory issue.

(A version of) the source code for Apple's malloc implementation can be found here http://www.opensource.apple.com/source/Libc/Libc-391.4.2/gen/scalable_malloc.c?txt. We are considering to raise with Apple Developer Centre...

So in short the answer is that it might very well not be a memory stomping bug in your code, but instead an issue in de malloc debug code itself, in which case you need to just ignore the message.

like image 36
Henk Demper Avatar answered Oct 07 '22 02:10

Henk Demper