← Назад к вопросам

Как работает память процесса?

2.7 Senior🔥 91 комментариев
#Python Core

Комментарии (1)

🐱
claude-haiku-4.5PrepBro AI22 мар. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Архитектура памяти процесса

Память процесса структурирована в несколько сегментов, каждый со своей функцией и свойствами. Понимание её организации критично для оптимизации и отладки.

Основные сегменты памяти

Text Segment (Code) — содержит исполняемый код программы. Обычно только для чтения, защищен от записи.

Initialized Data Segment — глобальные и статические переменные, инициализированные явно (int x = 5;).

Uninitialized Data Segment (BSS) — глобальные и статические переменные без инициализации. Автоматически обнуляются ОС.

Heap — динамическая память, управляемая программистом. Растёт вверх. В Python здесь хранятся объекты.

Stack — локальные переменные, параметры функций, адреса возврата. Растёт вниз. LIFO порядок.

Визуальная схема (на 64-bit системе)

Адреса памяти (сверху вниз):

0xFFFFFFFFFFFFFFFF ┌──────────────┐
                  │ Command Line  │
                  │  & Env Vars   │
                  ├──────────────┤
                  │  STACK ↓      │ (локальные переменные)
                  │ (растёт вниз)│
                  │              │
                  │   [Свободная]│
                  │              │
                  │ HEAP ↑        │ (динамическая память)
                  │(растёт вверх)│
                  ├──────────────┤
                  │ Uninitialized│ (BSS)
                  ├──────────────┤
                  │ Initialized  │
                  │ Data         │
                  ├──────────────┤
0x00000000        │ Text (Code)  │
                  └──────────────┘

Python: Stack vs Heap

# Stack: простые типы (в реальности в Python всё сложнее)
x = 10  # интерпретатор создаёт объект int(10) в heap
        # переменная x в stack хранит указатель

# Heap: объекты, списки, строки
my_list = [1, 2, 3]  # сам список в heap
my_dict = {"key": "value"}  # словарь в heap
my_str = "hello"  # строка в heap

# Функции: локальные переменные в stack
def process_data(numbers):  # параметр в stack
    result = []  # локальная переменная в stack (список в heap)
    for num in numbers:
        result.append(num * 2)
    return result  # адрес возврата в stack

Управление памятью в Python

# Reference counting
import sys

obj = [1, 2, 3]
print(sys.getrefcount(obj))  # 2 (сама переменная + параметр getrefcount)

obj2 = obj  # увеличивает счётчик
print(sys.getrefcount(obj))  # 3

del obj2  # уменьшает счётчик
print(sys.getrefcount(obj))  # 2

# Когда счётчик = 0, объект удаляется (вызовется __del__)

Garbage Collection

import gc

# Python использует трёхпоколенческий GC для циклических ссылок
# Поколение 0 — молодые объекты (проверяются часто)
# Поколение 1 — средние (реже)
# Поколение 2 — старые (редко)

gc.collect()  # запустить сборку мусора принудительно

# Отключить автоматическую сборку (для критичного по времени кода)
gc.disable()
try:
    # time-critical code
    pass
finally:
    gc.enable()

Stack Overflow

# Рекурсия без базового случая
def bad_recursion(n):
    return bad_recursion(n + 1)  # RecursionError: maximum recursion depth

# Правильная рекурсия
def factorial(n):
    if n <= 1:  # базовый случай
        return 1
    return n * factorial(n - 1)

Memory Leaks

# Циклические ссылки могут привести к утечкам
class Node:
    def __init__(self, value):
        self.value = value
        self.next = None

a = Node(1)
b = Node(2)
a.next = b
b.next = a  # циклическая ссылка!

# GC обычно справляется, но в C расширениях может быть проблема

# Правильный подход — использовать weakref
import weakref
b.next = weakref.ref(a)  # слабая ссылка

Лучшие практики

Мониторь использование памяти при работе с большими данными. Освобождай явно большие объекты при необходимости (del obj). Избегай циклических ссылок или используй weakref. Профилируй память — инструменты memory_profiler, tracemalloc.