LastSecondsToLive
LastSecondsToLive

Reputation: 744

Malloc doesn't return NULL

I just tested malloc with a huge memory request and it didn't return NULL. I already heard this but the BSD (I'm on a mac) man-page says:

RETURN VALUES
If successful, calloc(), malloc(), realloc(), reallocf(), and valloc() functions return a pointer to allocated memory. If there is an error, they return a NULL pointer and set errno to ENOMEM.

How can I check correctly and reliable, that the returned pointer points to a valid block of requested size?

EDIT: I just saw this post. Same for BSD I guess?

EDIT 2: The code:

typedef struct {
    uint8_t red;
    uint8_t green;
    uint8_t blue;
} RGB_TYPE;

int main() {
    RGB_TYPE *field = malloc(50000 * 50000 * sizeof(RGB_TYPE));

    if (!field)
        return -1;

    ... write to field (SEG_FAULT) ... 

    return 0;
}

Upvotes: 3

Views: 1006

Answers (1)

chqrlie
chqrlie

Reputation: 144490

The cause for your problem is somewhat tricky:

50000*50000*sizeof(RGB_TYPE) is evaluated as (size_t)(50000 * 50000) * sizeof(RGB_TYPE). The multiplication associates left to right, so the first multiplication is performed with int arithmetics and overflows since 2500000000 is larger than INT_MAX on your platform.

Integer overflow invokes undefined behavior, and your platform (clang) may generate silly code on this case. It can produce a diagnostic if instructed to (clang -Wall or clang -Weverything). In any case, your code crashes because the array does not have the expected size.

Change the code to

RGB_TYPE *field = malloc(sizeof(RGB_TYPE) * 50000 * 50000);

Furthermore, allocating 7.5 GB of memory might be possible on your computer. It will depend on system configuration, but it is not unrealistic that OS/X will allow that even if you have only 8GB of RAM.

EDIT: On my Mac, your code indeed does not produce a warning with clang -Weverything, which is a real nuisance, and tries to allocate 18446744068324649728 bytes. I get a runtime warning from malloc:

malloc-test(53877,0x7fff79dbe000) malloc: 
   *** mach_vm_map(size=18446744068324651008) failed (error code=3)
   *** error: can't allocate region
   *** set a breakpoint in malloc_error_break to debug

and malloc returns NULL. You probably have a different version of the tools and runtime library.

Upvotes: 5

Related Questions