Я пытаюсь переписать malloc и calloc, мой вопрос о реализации calloc, а не о том, как его использовать.
Всегда следует использовать calloc()
вместо malloc()+memset()
, потому что это может использовать преимущества copy-on-write (COW).
Некоторые calloc
реализованы так:
void * calloc(size_t nelem, size_t elsize)
{
void *p;
p = malloc (nelem * elsize);
if (p == 0)
return (p);
bzero (p, nelem * elsize);
return (p);
}
Но они вообще не используют COW (и не проверяют переполнение).
Если эти реализации не вызывают bzero()
, они должны предполагать, что получаемые ими страницы с mmap
заполнены нулями. Вероятно, они из-за соображений безопасности, мы не хотим утечки данных из других процессов, но я не могу найти стандартную ссылку на это.
Вместо использования MAP_ANON
мы могли бы mmap
из /dev/zero
:
fd = open("/dev/zero", O_RDWR);
a = mmap (0, 4096e4, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_FILE, fd, 0);
Но /dev/zero
не требуется POSIX, и можно было бы легко сделать sudo mv /dev/zero /dev/foo
, нарушив мою реализацию.
Как правильно переписать calloc()
, соблюдая принцип копирования при записи?
calloc()
иmalloc()
, вероятно, включает в себя выполнение соответствующего системного вызова. Детали, поневоле, зависят от системы. - person John Bollinger   schedule 20.10.2017mmap
, например, если выделение достаточно велико, аmmap
имеет параметр, гарантирующий нулевое заполнение (например,MAP_ANONYMOUS
в Linux). Хотя я не уверен, что это обычная оптимизация. - person rici   schedule 20.10.2017mmap
ядро всегда очищает память, так как вы не оставляете память от других процессов в нем (однако, я думаю, это, вероятно, гарантировано только в Linux). Так что в этом случае память уже должна быть обнулена. Вам нужно будет только обнулить память, если она поступает из одного из ваших пулов. - person Cassandra Fox   schedule 20.10.2017nelem * elsize
опасен и часто является источником дыр в безопасности. Вы должны проверить наличие переполнения там (ключевое слово:__builtin_mul_overflow()
) - person ensc   schedule 21.10.2017