Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Архитектура памяти процесса
Память процесса структурирована в несколько сегментов, каждый со своей функцией и свойствами. Понимание её организации критично для оптимизации и отладки.
Основные сегменты памяти
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.