Как только что сказал какой-то программист, чувак , в спецификации C не указана область, в которую должны быть помещены автоматические переменные. Но компиляторы обычно увеличивают стек, чтобы разместить их там. Однако они могут заканчиваться в области .data, и они будут, если они, например, будут определены как static char *pointer1
.
Значения инициализации могут существовать или не существовать в программной области. В вашем случае, поскольку тип значений - int
, большинство архитектур вместо встроенных инициализаций будут использовать соответствующие машинные инструкции, если доступны инструкции с соответствующими встроенными операторами. Например, в x86_64 будет выполнена одна операция mov
/ movq
для помещения 0 (NULL) или другого целого числа в соответствующее место в памяти стека.
Однако переменные, инициализированные с глобальной областью действия, такие как static char string[40] = "Hello world"
или другие инициализированные глобальные переменные, попадают в область .data
и занимают там место. Вместо этого компиляторы могут помещать объявленные, но неопределенные глобальные переменные в области .bss
.
Вопрос , так как pointer1 = malloc (80), относится ли он к секции стека? нечетко определен, поскольку содержит две вещи.
Значение pointer1
- это значение, которое будет сохранено в &pointer1
. Адрес, который, учитывая вышеизложенное, возможно, компилятор поместил в стек.
Результатом malloc(80)
является значение, которое относится к области в куче, другой области, динамически выделяемой за пределами сопоставленного программного пространства.
В Linux результат вызова malloc
может даже создать новую область памяти с NULL-поддержкой (то есть временную область, которая не постоянно хранится в файле; хотя она может быть заменена ядром).
В сущности, вы можете думать о том, как ведет себя malloc (80), как что-то вроде (не принимая во внимание free (), поэтому это упрощение ):
int space_left = 0; void *last_mapping = NULL;
void *malloc(int req) {
void *result;
if (space_left < req) {
last_mapping = mmap(NULL, MALLOC_CHUNK_LENGTH, PROT_READ|PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
space_left = MALLOC_CHUNK_LENGTH;
}
space_left -= req;
result = last_mapping;
last_mapping += req;
return result;
}
Огромная разница между вызовами malloc
и mmap
с помощью MAP_PRIVATE состоит в том, что mmap - это системный вызов Linux, который должен переключать контекст ядра, выделять новую карту памяти и сбрасывать уровень MMU для каждого выделенного блока памяти, в то время как malloc может быть более интеллектуальным и использовать один большой регион в качестве «кучи» и управлять различными malloc и free в пространстве пользователя после инициализации кучи (до тех пор, пока куча не исчерпает пространство, где может потребоваться управление несколькими кучами).