Функции malloc
и calloc
технически не выделяют память, несмотря на их имя. Они фактически выделяют части адресного пространства вашей программы с правами чтения / записи на уровне ОС. Это небольшая разница, которая не актуальна большую часть времени.
Эта программа, как написано, использует только адресное пространство. В конце концов, calloc
начнет возвращать NULL, но программа продолжит работу.
#include <stdlib.h>
// Note main should be int.
int main() {
while (1) {
// Note calloc should not be cast.
int *a = calloc(65536, sizeof(int));
}
}
Если вы пишете по адресам, возвращенным из calloc, это заставит ядро выделить память для поддержки этих адресов.
#include <stdlib.h>
#include <string.h>
int main() {
size_t size = 65536 * 4;
while (1) {
// Allocates address space.
void *p = calloc(size, 1);
// Forces the address space to have allocated memory behind it.
memset(p, 0, size);
}
}
Недостаточно записи в одно место в блоке, возвращаемом из calloc
, потому что степень детализации для выделения фактической памяти составляет 4 КиБ (размер страницы ... 4 КиБ является наиболее распространенным). Так что вы можете просто написать на каждой странице.
А как насчет 64-битного случая?
Существуют некоторые накладные расходы на распределение адресного пространства. В 64-битной системе вы получите что-то вроде 40 или 48 бит адресного пространства, из которых примерно половина может быть выделена программе, что составляет не менее 8 ТиБ. В 32-разрядной системе это составляет около 2 ГБ или около того (в зависимости от конфигурации ядра).
Таким образом, в 64-битной системе вы можете выделить ~ 8 ТиБ, а в 32-битной системе вы можете выделить ~ 2 ГиБ, и из-за накладных расходов возникают проблемы. Обычно на каждый звонок накладывается небольшая сумма на malloc
или calloc
.
См. Также Почему malloc + memset медленнее, чем calloc?