Я экспериментировал с realloc
, придавая ему большие и большие размеры и проверяя, использовался ли один и тот же блок или нет:
int main ( void )
{
char * newstr, * prevstr = NULL;
size_t newsize, prevsize = 0;
printf ("We play with realloc\n");
while (1) {
newsize = prevsize + 1 + prevsize/3; /* add 33% */
newstr = realloc(prevstr, newsize);
if (newstr == NULL) {
printf ("could not alloc newsize=%zu. Sorry\n", newsize);
break;
} else {
printf ("newsize=%zu successfully alloc'ed\n", newsize);
if (newstr == prevstr) {
printf ("newstr = prevstr:\tSame block reused\n");
} else {
printf ("newstr != prevstr:\tNew block alloc'ed\n");
}
prevstr = newstr; prevsize = newsize;
}
}
return (EXIT_SUCCESS);
}
Как и ожидалось, один из них достигает точки, где размер слишком велик, а realloc
не может ответить на запрос. Согласно руководству, realloc
должен возвращать NULL
и устанавливать errno = ENOMEM
, когда это не удастся.
Это не то, что происходит, когда я запускаю приведенный выше код на своей машине, Mac с "Darwin Kernel Version 15.0.0". Вместо того, чтобы возвращать NULL, код выходит из строя и говорит
malloc: *** mach_vm_map(size=153288611651584) failed (error code=3)
*** error: can't allocate region
*** set a breakpoint in malloc_error_break to debug
could not alloc newsize=153288611651277. Sorry
Это нормально? Что-то я не понял при чтении страницы руководства?
Это не важно для моего кода на данный момент, но я могу представить ситуации, в которых я хотел бы проверить, можно ли выделить память, не рискуя столкнуться. Существует ли стандартный способ проверки того, будет ли alloc работать без риска такого сбоя?
ADDED после того, как тайна решена (см. ответы ниже): нет сбоя, просто сообщение о системной ошибке от malloc, которое мешает ожидаемому результату. См. Ниже, как этого избежать.