Перейти к основному содержимому

Продвинутые операции с данными — итоги

Разработчику Аналитику Тестировщику Архитектору Инженеру

Кратко — что стоит унести из раздела "Продвинутые операции с данными". Если пункт кажется туманным — откройте указанную главу или оглавление.


FAQ — Часто задаваемые вопросы

Типичные сбои и ситуации при работе с данными в коде. Здесь — что делать и где копать в главах; определения для зачёта — в чек-листе.

Вопрос. Программа падает с "segmentation fault" или "access violation" сразу после работы с указателем — с чего начать?

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

Вопрос. Два процесса читают один и тот же "адрес", но данные разные — это баг ОС?

Ответ. У каждого процесса своё виртуальное адресное пространство: одинаковое число-адрес ссылается на разные физические байты. MMU переводит виртуальный адрес в физический по таблице страниц. Подробнее здесь — Адресация данных в памяти.

Вопрос. Число на одном компьютере читается правильно, на другом — "перевёрнутое" или мусор при чтении бинарного файла по сети.

Ответ. Разный порядок байтов (endianness): little-endian и big-endian по-разному раскладывают многобайтовое число. При обмене бинарными данными явно зафиксируйте порядок или используйте текстовый формат (JSON). Подробнее здесь — Биты, байты, машинные слова.

Вопрос. Сложил два больших положительных числа — получил отрицательное. Где ошибка?

Ответ. Переполнение фиксированного типа (int, int32): биты "перекрутились". В Java/C# переполнение молча обрезается; в C это неопределённое поведение для signed. Используйте тип побольше, BigInteger или проверку диапазона до операции. Подробнее здесь — Продвинутые операции с данными.

Вопрос. 3.14 + 0.01 в коде даёт 3.1499999999999995 — программа "не умеет в математику"?

Ответ. Числа с плавающей точкой хранятся приближённо в двоичном виде; сравнивать их через == опасно. Для денег и точных расчётов — decimal / BigDecimal; для сравнения float — допуск (epsilon). Подробнее здесь — Продвинутые операции с данными.

Вопрос. Пользователь ввёл "12abc" в поле возраста — парсер молча вернул 12 или упал.

Ответ. Нужна явная валидация: проверяйте весь ввод целиком, а не только префикс цифр. В JavaScript parseInt("12abc") вернёт 12; в строгих языках — исключение. Лучше regex или парсер с отказом при лишних символах. Подробнее здесь — Продвинутые операции с данными.

Вопрос. if (x = 5) вместо if (x == 5) — почему условие "всегда истинно"?

Ответ. В C-подобных языках присваивание возвращает присвоенное значение; x = 5 даёт 5 (truthy). Включайте предупреждения компилятора (-Wparentheses) или пишите константу слева: if (5 == x). Подробнее здесь — Продвинутые операции с данными.

Вопрос. Сравниваю две строки через == в Java — иногда "одинаковые" строки не равны.

Ответ. == для объектов сравнивает ссылки, а не символы. Для текста — equals(). Литералы в пуле могут совпасть по ссылке случайно; new String("a") — нет. Подробнее здесь — Продвинутые операции с данными.

Вопрос. Конкатенация строк в цикле на миллион итераций "вешает" программу.

Ответ. Каждый + создаёт новую строку — квадратичная стоимость. Используйте StringBuilder, StringBuffer, список с финальным join или буфер потока. Подробнее здесь — Продвинутые операции с данными.

Вопрос. Regex "нашёл" подстроку, но группа захвата пустая — паттерн вроде верный.

Ответ. Проверьте жадность квантификаторов (* vs *?), якоря ^/$, кодировку входа и экранирование спецсимволов. Тестируйте на минимальном примере и смотрите group(1) только если группа участвовала в совпадении. Подробнее здесь — Продвинутые операции с данными.

Вопрос. Скопировал объект в переменную b = a, изменил поле в b — и в a тоже поменялось.

Ответ. Это поверхностная копия по ссылке: обе переменные указывают на один объект. Для независимой копии — глубокое клонирование (structuredClone, сериализация, конструктор копирования). Подробнее здесь — Продвинутые операции с данными.

Вопрос. API вернул JSON, но JSON.parse падает — в браузере "Unexpected token".

Ответ. Ответ сервера часто HTML-страница ошибки вместо JSON (401, 502, редирект на login). Сначала проверьте HTTP-код и Content-Type, затем тело ответа в Network. Подробнее здесь — Маршалинг и анмаршалинг.

Вопрос. После десериализации JSON число 9007199254740993 стало 9007199254740992.

Ответ. JavaScript хранит все числа как IEEE-754 double — точность только до 2⁵³−1. Большие ID передавайте строкой или используйте библиотеку BigInt после парсинга. Подробнее здесь — Маршалинг и анмаршалинг.

Вопрос. Сервис упал с StackOverflowError при сериализации объекта.

Ответ. В графе объектов есть циклическая ссылка (A → B → A). JSON её не поддерживает; нужен обход с множеством посещённых узлов, @JsonIdentityInfo или смена модели данных. Подробнее здесь — Маршалинг и анмаршалинг.

Вопрос. Десериализация "чужого" pickle/Java-serialized объекта — почему это опасно?

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

Вопрос. Событие в 02:30 в день перехода на летнее время "исчезло" или продублировалось в логах.

Ответ. Локальное время не монотонно при DST: час может повториться или пропасть. Храните моменты в UTC (Instant, timestamptz), локаль показывайте только в UI. Подробнее здесь — Продвинутые операции с данными.

Вопрос. "31 января + 1 месяц" в коде дало 3 марта или упало с ошибкой.

Ответ. Календарная арифметика зависит от библиотеки: одни "переносят" на последний день месяца, другие — overflow. Явно зафиксируйте правило в требованиях и тестах на граничные даты. Подробнее здесь — Продвинутые операции с данными.

Вопрос. Разница двух дат "30 дней" на бумаге, а программа считает 29 или 31.

Ответ. Уточните единицу: календарные дни, рабочие дни или 24-часовые интервалы. Високосный год и часовые пояса меняют результат. Для договоров фиксируйте правило в коде и документации. Подробнее здесь — Продвинутые операции с данными.

Вопрос. Читаю гигабайтный лог в память целиком — процесс съел всю RAM и убит OOM-killer.

Ответ. Большие файлы обрабатывайте потоком: построчное чтение, chunk-буфер, pipeline. readAllBytes() уместен только для маленьких файлов с известным лимитом. Подробнее здесь — Продвинутые операции с данными.

Вопрос. Base64-строка в API на 30 % длиннее исходного файла — это ошибка кодирования?

Ответ. Base64 кодирует 3 байта в 4 символа — рост ~33 % нормален. Для бинарных вложений в JSON это ожидаемо; для больших файлов лучше отдельная загрузка или multipart. Подробнее здесь — Продвинутые операции с данными.

Вопрос. Хеш пароля в базе совпал у двух пользователей с разными паролями — SHA-256 "сломался"?

Ответ. Это коллизия хеш-функции (крайне редко для SHA-256) или одинаковый пароль у обоих. Для паролей используйте медленные алгоритмы с солью (bcrypt, Argon2), а SHA-256 — для контрольных сумм файлов. Подробнее здесь — Продвинутые операции с данными.

Вопрос. Побитовый сдвиг 1 << 31 дал отрицательное число на 32-битном int.

Ответ. Старший бит signed-типа — знак; переполнение при сдвиге интерпретируется как отрицательное. Используйте long, unsigned (где есть) или маски с явным & 0xFFFFFFFFL. Подробнее здесь — Биты, байты, машинные слова.

Вопрос. Программа тормозит на "простом" цикле по массиву — профайлер показывает cache miss.

Ответ. Обход не по порядку памяти (столбцы матрицы вместо строк) бьёт по кэшу CPU. Упорядочите доступ, сожмите структуру (SoA vs AoS), учитывайте выравнивание полей. Подробнее здесь — Адресация данных в памяти.

Вопрос. trim() убрал пробелы, но сравнение строк всё равно false — визуально одинаково.

Ответ. Внутри могут быть неразрывные пробелы (NBSP), zero-width символы или другая Unicode-нормализация. Выведите коды символов (charCodeAt, ord), нормализуйте через NFC/NFKC. Подробнее здесь — Продвинутые операции с данными.

Вопрос. Версия protobuf на сервере новее — клиент "не понимает" новые поля.

Ответ. Protobuf по умолчанию игнорирует неизвестные поля при чтении (forward compatibility), но менять номера и типы полей нельзя. Новые поля добавляйте с новыми tag; deprecated помечайте, но номер не переиспользуйте. Подробнее здесь — Маршалинг и анмаршалинг.

Вопрос. Новичок путает "бит" в коде (&, |) и "бит" как единицу информации в курсе.

Ответ. Побитовые операции работают с отдельными двоичными разрядами числа (флаги, маски); логический "бит данных" — абстракция хранения. Контекст: флаги прав доступа — побитово; текст в UTF-8 — последовательность байт. Подробнее здесь — Биты, байты, машинные слова.

Вопрос. Случайные числа в тестах каждый раз разные — тесты "мигают".

Ответ. Генератор псевдослучайный — задайте фиксированный seed в тестах (Random(42)). В проде seed берут из энтропии ОС; для криптографии — SecureRandom, /dev/urandom. Подробнее здесь — Продвинутые операции с данными.

Вопрос. Записал null в JSON — на другой стороне поле "пропало" или стало undefined.

Ответ. JSON явно поддерживает null; в JavaScript undefined сериализуется с пропуском ключа. Согласуйте контракт API: optional vs nullable, используйте JSON Schema или OpenAPI. Подробнее здесь — Маршалинг и анмаршалинг, Конфигурации и данные.

Вопрос. Память процесса растёт, хотя объекты "удалил" — утечка?

Ответ. В языках с GC объект жив, пока на него есть ссылка (статическое поле, кэш, замыкание, очередь событий). Профилируйте heap dump, ищите удерживающие ссылки. В C/C++ — явный free и инструменты вроде Valgrind. Подробнее здесь — Адресация данных в памяти.

Вопрос. Что такое виртуальная память простыми словами?

Ответ. Каждый процесс видит своё линейное адресное пространство; ОС и MMU отображают виртуальные адреса на физическую RAM и диск (swap). Изоляция процессов и защита — следствие этой схемы. Подробнее здесь — Адресация данных в памяти.

Вопрос. Чем отличается сериализация от маршалинга?

Ответ. Сериализация — объект → байты/текст для хранения или сети. Маршалинг шире: упаковка с учётом RPC, версий, платформы и контракта между процессами. На практике термины пересекаются; важнее формат (JSON, protobuf) и безопасность десериализации. Подробнее здесь — Маршалинг и анмаршалинг.

Вопрос. Зачем нужен Base64 и когда его используют?

Ответ. Base64 кодирует бинарные данные в текст ASCII, чтобы передать их через JSON, email или URL без порчи байт. Размер вырастает примерно на треть — это нормально. Подробнее здесь — Продвинутые операции с данными.

Вопрос. Little endian и big endian — в чём разница?

Ответ. Это порядок байтов в многобайтовом числе: младший байт первым (little) или старший (big). x86 — little endian; сетевые протоколы часто big endian. При обмене бинарниками порядок нужно явно согласовать. Подробнее здесь — Биты, байты, машинные слова.

Вопрос. Сколько бит в байте и почему именно 8?

Ответ. В современных системах 1 байт = 8 бит — минимальная адресуемая единица RAM. Исторически размер байта различался; сегодня октет и байт в быту совпадают. Подробнее здесь — Биты, байты, машинные слова.

Вопрос. Что такое указатель (pointer) в программировании?

Ответ. Указатель хранит адрес другого значения в памяти, а не само значение. Через него читают и меняют данные; ошибки указателей — частая причина падений в C/C++. Подробнее здесь — Адресация данных в памяти.

Вопрос. Как правильно хранить дату и время в базе и в коде?

Ответ. Храните момент в UTC (timestamptz, Instant); часовой пояс и локаль — только при отображении пользователю. Так избегают ошибок DST и сравнения "локальных" дат. Подробнее здесь — Продвинутые операции с данными.

Вопрос. Что такое Unix timestamp и почему его везде используют?

Ответ. Это число секунд (или миллисекунд) с 1 января 1970 UTC — компактно, сортируется, без двусмысленности локали. Для людей форматируют отдельно. Подробнее здесь — Продвинутые операции с данными.

Вопрос. JSON или XML — что лучше для REST API?

Ответ. Для большинства REST и мобильных API — JSON: меньше, проще парсить. XML нужен при XSD-контрактах, SOAP, гос. интеграциях. Подробнее здесь — Маршалинг и анмаршалинг, JSON.

Вопрос. Что такое protobuf и чем он лучше JSON?

Ответ. Protocol Buffers — бинарный формат со схемой: компактнее и быстрее JSON, строгие типы. Минус — нечитаем человеком без инструментов. Типичен в gRPC и микросервисах. Подробнее здесь — Маршалинг и анмаршалинг, MessagePack, BSON, Protobuf.

Вопрос. Чем хеширование отличается от шифрования?

Ответ. Хеш — односторонняя функция (SHA-256); из хеша исходник не восстановить. Шифрование обратимо при ключе. Пароли хешируют с солью (bcrypt), трафик шифруют (TLS). Подробнее здесь — Продвинутые операции с данными.

Вопрос. Что такое парсинг строки и чем он отличается от split?

Ответ. Парсинг извлекает структуру по правилам (CSV, JSON, лог, URL). split — грубое деление по разделителю без семантики. Для форматов с кавычками и экранированием нужен полноценный парсер. Подробнее здесь — Продвинутые операции с данными.

Вопрос. Явное и неявное приведение типов — что это?

Ответ. Неявное — компилятор сам расширяет intlong (риск потери). Явное(int) x или parseInt: программист отвечает за корректность. Подробнее здесь — Продвинутые операции с данными.

Вопрос. Поток данных (stream) — что это в программировании?

Ответ. Последовательная обработка данных порциями, без загрузки всего файла в память: чтение логов, HTTP-body, видео. Буферизация снижает число системных вызовов. Подробнее здесь — Продвинутые операции с данными.

Вопрос. Глубокое и поверхностное копирование объекта — в чём разница?

Ответ. Поверхностная копия дублирует поля; вложенные объекты остаются общими. Глубокая рекурсивно клонирует всё дерево. В JavaScript — structuredClone; в Python — copy.deepcopy. Подробнее здесь — Продвинутые операции с данными.

Вопрос. Что такое UTF-8 и зачем он нужен?

Ответ. UTF-8 — кодировка Unicode переменной длины: ASCII совместим, кириллица и эмодзи в одном файле. Для текста в коде, JSON и HTTP задавайте UTF-8 явно. Подробнее здесь — Биты, байты, машинные слова, Текстовые форматы.

Вопрос. Побитовые операции AND OR XOR — для чего они в коде?

Ответ. Маски флагов, права доступа, сжатие, хеши, низкоуровневая оптимизация. Пример: проверить бит через value & (1 << n). Подробнее здесь — Продвинутые операции с данными, Биты, байты, машинные слова.

Вопрос. Как сравнить две даты в JavaScript или Python?

Ответ. Сравнивайте нормализованные моменты (UTC epoch или datetime с tz), а не строки DD.MM.YYYY. Библиотеки: date-fns, datetime (Python 3.9+), java.time. Подробнее здесь — Продвинутые операции с данными.

Вопрос. Что такое cache locality и при чём здесь массивы?

Ответ. CPU быстрее читает соседние ячейки памяти (кэш-линия). Последовательный обход массива эффективнее случайного доступа по связному списку. Подробнее здесь — Адресация данных в памяти.

Вопрос. Null pointer exception — что это и как избежать?

Ответ. Обращение к ссылке со значением null (Java, C#) или нулевому указателю (C). Проверки, Optional, nullable-аннотации, инициализация по умолчанию. Подробнее здесь — Продвинутые операции с данными.

Вопрос. Что такое immutable строка и почему строки в Java неизменяемы?

Ответ. После создания содержимое не меняется — любая "правка" создаёт новый объект. Плюсы: потокобезопасность, кэш hash, безопасность; минус — конкатенация в цикле дорогая без StringBuilder. Подробнее здесь — Продвинутые операции с данными.

Вопрос. Как передать файл через API — Base64 или multipart?

Ответ. Мелкие файлы можно в JSON как Base64; для больших — multipart/form-data или отдельная загрузка по presigned URL. Base64 раздувает размер ~33 %. Подробнее здесь — Маршалинг и анмаршалинг.

Вопрос. Что такое MMU и зачем он нужен процессору?

Ответ. Memory Management Unit переводит виртуальные адреса в физические, проверяет права доступа (read/write/execute) и поддерживает страничную память. Подробнее здесь — Адресация данных в памяти.


Что запомнить

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

Центральным понятием является адрес в памяти — уникальный числовой идентификатор, позволяющий процессору точно определять местоположение каждого байта данных. Современные системы используют виртуальную адресацию, изолирующую процессы друг от друга и обеспечивающую безопасность и стабильность. Аппаратный блок MMU преобразует виртуальные адреса в физические, используя страничную модель, которая лежит в основе механизма виртуальной памяти.

Данные в компьютере представлены через иерархию единиц: бит — минимальная логическая единица; байт — минимальная адресуемая единица; машинное слово — естественная единица обработки для конкретного процессора. Рассмотрены также нетрадиционные модели, такие как вероятностные биты (P-биты) и кубиты, демонстрирующие альтернативные подходы к вычислениям.

Операции с данными выходят далеко за рамки простого чтения и записи. Они включают:

  • Преобразование типов — явное и неявное изменение представления данных;
  • Парсинг — извлечение структурированной информации из неструктурированного текста;
  • Математические и побитовые операции — манипуляции с числовыми значениями на разных уровнях абстракции;
  • Работу со строками — конкатенацию, поиск, замену, форматирование и другие текстовые преобразования;
  • Обработку потоков — последовательную работу с большими объёмами данных, включая кодирование, хеширование и сериализацию;
  • Манипуляции с объектами — создание, клонирование, сравнение и валидацию сложных структур;
  • Операции с датами и временем — учёт часовых поясов, високосных лет и календарных аномалий.

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

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


Что читать дальше

  • Конфигурации и данные — JSON, YAML, XML на практике.
  • SQL и NoSQL — хранение и запросы к структурированным данным.
  • Разделы языков (JavaScript, Python) — типы, даты и сериализация в конкретной среде.

Куда идти дальше

Полный маршрут — на странице о разделе.

Проверьте себя: Чек-лист самопроверки.