Открыть сервис

Сегмент данных

Сегмент данных — это область оперативной памяти, выделяемая программе для хранения глобальных и статических переменных, а также констант времени компиляции. В контексте архитектуры компьютерных систем и программирования сегмент данных является одной из ключевых частей адресного пространства процесса, наряду с сегментом кода (текстовым сегментом), стеком и кучей. Он характеризуется фиксированным размером, определяемым на этапе компиляции, и доступен для чтения и записи (за исключением подсегмента констант, который может быть защищён от записи).

Структура и размещение в памяти

Сегмент данных традиционно располагается в виртуальном адресном пространстве процесса после сегмента кода. В типичной модели памяти программы на языках C/C++ он делится на две основные части:

Отдельно может выделяться сегмент только для чтения (.rodata), в котором хранятся константы (строковые литералы, константные массивы и структуры, определённые с ключевым словом const). В некоторых архитектурах и операционных системах этот подсегмент помещается в сегмент кода или в отдельную область с защитой от записи.

Отличия от других областей памяти

Жизненный цикл и инициализация

При запуске исполняемого файла загрузчик операционной системы (например, ld-linux.so в Linux или загрузчик Windows) выполняет следующие действия с сегментом данных:

  1. Считывает из заголовка исполняемого файла (формат ELF, PE, Mach-O) информацию о расположении и размерах секций .data, .bss и .rodata.
  2. Отображает секцию .data в виртуальную память процесса, копируя в неё начальные значения из файла на диске.
  3. Выделяет память для секции .bss и заполняет её нулями.
  4. Устанавливает права доступа: для .data — чтение и запись; для .rodata — только чтение; для .text — чтение и выполнение.

Переменные в сегменте данных существуют до завершения программы. Они доступны из любой функции текущего процесса (если не скрыты областью видимости), что делает их удобным инструментом для обмена данными между функциями, но одновременно источником потенциальных проблем с многопоточностью и безопасностью.

Примеры содержимого

Рассмотрим фрагмент кода на языке C:

```c

include <stdio.h>

int global_init = 100; // .data int global_uninit; // .bss const char *message = "Hello"; // message — .data, строка "Hello" — .rodata static int static_var = 5; // .data

int main() { static int local_static = 0; // .bss (обнуляется) int local_auto = 10; // стек return 0; } ```

Значение в различных парадигмах программирования

В процедурных языках (C, Pascal, Fortran) сегмент данных является основным способом хранения глобального состояния программы. В объектно-ориентированных языках (C++, Java, C#) глобальные переменные в чистом виде используются реже, однако статические поля классов и статические локальные переменные также размещаются в сегменте данных. Например, в Java статические поля класса хранятся в области Metaspace (аналог сегмента данных в контексте виртуальной машины), а в C++ — непосредственно в .data или .bss.

В функциональных языках (Haskell, Erlang) глобальные изменяемые переменные обычно отсутствуют или ограничены, что снижает роль сегмента данных в таких системах.

Безопасность и уязвимости

Сегмент данных может становиться объектом атак. Наиболее известные проблемы:

Для защиты применяются методы: рандомизация адресного пространства (ASLR), запрет исполнения кода в сегменте данных (NX-бит), статический анализ кода и использование безопасных функций копирования памяти.

Особенности в разных операционных системах

Источники

BFOmetr — база данных и аналитика по компаниям России.

На главную BFOmetr →