Когда пользователь нажимает Ctrl+C, кажется, что операционная система просто "запоминает" выделенный фрагмент. На деле за одну секунду происходит несколько системных вызовов, выделяется отдельный блок оперативной памяти, а сами данные упаковываются сразу в несколько форматов одновременно. Ниже разобрано, где физически лежит содержимое буфера обмена в Windows, кто им владеет, почему картинка занимает в разы больше места, чем текст, и что случается с этими данными после перезагрузки.
Из чего технически состоит буфер обмена в Windows на уровне памяти
У буфера обмена Windows нет отдельного "хранилища" вроде папки или базы данных. Это программная абстракция поверх обычной оперативной памяти: система резервирует блок глобальной памяти через функцию GlobalAlloc, блокирует его вызовом GlobalLock, чтобы получить указатель для записи, и снимает блокировку через GlobalUnlock после заполнения. Полученный блок передается ядру системными вызовами OpenClipboard, EmptyClipboard, SetClipboardData и CloseClipboard. После вызова SetClipboardData владельцем этого куска памяти становится не приложение, а сама операционная система: программа больше не должна освобождать или блокировать этот блок, иначе содержимое буфера окажется повреждено. Физически эта область памяти ничем не отличается от обычной кучи любого другого процесса, просто доступ к ней регулируется отдельным набором API и правами текущего сеанса пользователя.
У буфера обмена есть понятие владельца: окно, которое последним вызвало SetClipboardData, становится clipboard owner и обязано откликаться на системные сообщения, если оно решило отложить фактическую подготовку данных. Такой режим называется отложенным рендерингом: приложение сообщает Windows, что определенный формат доступен, но не копирует данные в память сразу, а готовит их только в момент запроса через сообщения WM_RENDERFORMAT и WM_RENDERALLFORMATS. Это экономит оперативную память в случаях, когда пользователь скопировал большой объект, но так и не вставил его никуда до следующего копирования. Как только владелец буфера закрывается или сам вызывает EmptyClipboard для нового фрагмента, отложенные форматы, которые он не успел отрендерить, исчезают вместе с ним.
Что происходит в памяти в момент нажатия Ctrl+C
Последовательность действий жестко зафиксирована архитектурой Windows. Сначала приложение считывает выделенный пользователем фрагмент экрана или документа. Затем оно преобразует его во внутренний формат, понятный системе: обычный текст, текст с разметкой или растровое изображение. После этого данные записываются в память буфера, а прежнее содержимое немедленно удаляется, потому что буфер Windows по умолчанию хранит только один актуальный набор данных за раз. При операции "вырезать" добавляется еще один шаг: помимо копирования в буфер, исходный объект помечается на удаление из документа, поэтому вставка выглядит как перемещение, а не дублирование. Все перечисленные операции происходят в оперативной памяти и занимают доли миллисекунды, диск в этой цепочке не участвует вовсе.
Какие форматы данных Windows создает для одного скопированного фрагмента
Ключевая особенность буфера обмена в Windows состоит в том, что одно действие копирования почти никогда не создает только одну запись в памяти. Приложение может вызвать SetClipboardData несколько раз подряд для одного и того же фрагмента, каждый раз с новым идентификатором формата, и все эти представления хранятся параллельно, пока не появится следующая операция копирования. У каждого формата есть числовой код: CF_TEXT (1) для однобайтового ANSI-текста, CF_BITMAP (2) для указателя на растровое изображение, CF_METAFILEPICT (3) для векторных метафайлов, CF_DIB (8) для независимого от устройства растра, CF_UNICODETEXT (13) для текста в кодировке UTF-16, CF_LOCALE (16) для языковых настроек и CF_DIBV5 (17) для расширенного формата растра с поддержкой цветовых профилей. Если скопировать ячейку из Excel, в памяти одновременно появятся варианты Biff, CSV, RTF, HTML Format и OLE-объект, потому что разные приложения умеют вставлять один и тот же фрагмент по-разному. Реальный дамп буфера после копирования диапазона ячеек показывает такую картину: формат CF_DIB занимает 57368 байт; CF_DIBV5 занимает 57452 байта; Rich Text Format занимает 3071 байт; HTML Format занимает 2344 байта; CF_UNICODETEXT занимает всего 22 байта; суммарный объем памяти под все представления одного скопированного диапазона достигает 150642 байт. Именно поэтому копирование даже короткой строки способно занять в памяти значительно больше места, чем кажется на первый взгляд.
Чтобы другие приложения узнавали о смене содержимого буфера, Windows поддерживает механизм уведомлений. Раньше для этого использовалась цепочка окон просмотра буфера обмена, выстроенная функцией SetClipboardViewer: каждое окно из цепочки получало сообщение WM_DRAWCLIPBOARD и должно было передать его следующему звену, а обрыв цепочки из-за аварийного завершения одного из приложений мог сломать уведомления для всех остальных. Современный способ надежнее: приложение регистрируется через AddClipboardFormatListener и получает сообщение WM_CLIPBOARDUPDATE напрямую от системы без риска повредить общую цепочку. Заглянуть внутрь текущего содержимого буфера без вставки можно специализированными утилитами вроде ClipSpy или InsideClipboard, которые перечисляют все доступные форматы через EnumClipboardFormats и показывают точный размер каждого блока памяти в байтах.
Как хранится скопированное изображение и почему оно занимает так много памяти
Текст в буфере обмена почти всегда компактен, потому что кодируется как последовательность символов. Картинка устроена принципиально иначе: формат CF_DIB представляет собой заголовок структуры BITMAPINFO, за которым в память построчно записывается каждый пиксель изображения без сжатия. Скриншот экрана в разрешении Full HD в 24-битном цвете без сжатия занимает в оперативной памяти около шести мегабайт, и это без учета дублирующих представлений вроде CF_DIBV5 или CF_BITMAP, которые Windows создает параллельно для совместимости со старыми приложениями. Формат CF_BITMAP хранит не сами пиксели, а хендл на объект GDI, который зависит от текущей палитры экрана, поэтому современные приложения предпочитают публиковать в буфер именно CF_DIB или CF_DIBV5, а систему просят самой досчитать совместимые представления по запросу. Чем выше разрешение и глубина цвета скопированного изображения, тем сильнее растет объем оперативной памяти, занятой буфером, и эта память остается зарезервированной до следующего копирования или явной очистки буфера.
Расчет объема здесь прямолинейный: экран разрешением 1920 на 1080 точек при 24 битах на пиксель дает произведение 1920 умножить на 1080 умножить на 3 байта, то есть чуть больше 6 220 000 байт на один несжатый кадр, и это только для формата CF_DIB. Если приложение параллельно публикует в буфер еще и CF_DIBV5 с расширенным заголовком цветового профиля, суммарный расход памяти на одно и то же изображение превышает 12 мегабайт. Некоторые графические редакторы дополнительно кладут в буфер собственный зарегистрированный формат со сжатым PNG внутри, тогда рядом с двумя тяжелыми несжатыми представлениями в памяти оказывается еще и компактная копия того же изображения в несколько раз меньшего размера, специально для приложений, которые умеют распаковывать PNG самостоятельно.
Ключевые технические факты о хранении данных в буфере обмена Windows стоит зафиксировать отдельно:
- содержимое буфера всегда находится в оперативной памяти и никогда не пишется в отдельный файл на диске автоматически;
- владельцем блока памяти после вызова SetClipboardData становится операционная система, а не приложение, которое поместило туда данные;
- одно копирование почти всегда создает сразу несколько параллельных форматов одного и того же фрагмента;
- изображения занимают в памяти на порядок больше места, чем текст, из-за несжатого построчного хранения пикселей;
- история буфера обмена через сочетание Windows плюс V хранится в памяти отдельного процесса службы cbdhsvc, а не в реестре или базе данных.
Куда попадают данные при работе истории буфера обмена и сочетания Windows плюс V
С обновления октября 2018 года в Windows 10 и в Windows 11 появилась функция истории буфера обмена, вызываемая сочетанием клавиш Windows плюс V. За нее отвечает отдельная служба cbdhsvc, которая запускается через процесс svchost.exe с параметрами -k ClipboardSvcGroup -p -s cbdhsvc и хранит до двадцати пяти последних скопированных элементов не на диске, а в памяти собственного процесса, в динамической куче. Библиотека, реализующая эту логику, физически лежит в системном каталоге C:\Windows\System32\cbdhsvc.dll. Пока функция истории не включена вручную в настройках системы, старые записи после закрытия приложения или перезагрузки компьютера безвозвратно теряются вместе с содержимым оперативной памяти. Специализированные утилиты для анализа памяти способны находить остатки истории буфера обмена внутри кучи процесса cbdhsvc даже без обращения к штатному интерфейсу Windows плюс V, потому что операционная система не обязана мгновенно затирать освобожденные страницы памяти нулями.
Что происходит с содержимым буфера при переходе в облачную синхронизацию
Если в параметрах системы включить облачную синхронизацию буфера обмена, данные перестают быть строго локальными. Скопированный фрагмент по-прежнему сначала оказывается в оперативной памяти текущего устройства, но затем служба cbdhsvc отправляет его копию на серверы Microsoft, привязанные к учетной записи пользователя, чтобы тот же текст или изображение можно было вставить на другом компьютере под тем же аккаунтом. Передача происходит по зашифрованному каналу, а хранение на стороне серверов заявлено как временное, однако сам факт выхода содержимого буфера за пределы локальной оперативной памяти меняет модель угроз: теперь скопированный фрагмент существует не только в куче конкретного процесса на конкретной машине, но и во временном хранилище облачного сервиса. Отключение этой функции возвращает буфер обмена к исходному поведению, при котором данные не покидают оперативную память локального устройства ни при каких обстоятельствах.
Какие риски безопасности связаны с хранением данных в оперативной памяти
Поскольку буфер обмена физически представляет собой обычный участок оперативной памяти без встроенного шифрования, любой процесс с правами текущего пользователя способен прочитать его содержимое через стандартный вызов GetClipboardData. Этим пользуются вредоносные программы, которые незаметно отслеживают буфер обмена и подменяют скопированные номера криптовалютных кошельков на кошельки злоумышленника прямо в момент вставки. Отдельная категория рисков связана с криминалистическим анализом: исследование извлечения буфера обмена из образов оперативной памяти показало, что содержимое буфера можно восстановить из дампа RAM даже спустя значительное время после копирования, потому что операционная система освобождает память лениво и не гарантирует немедленного затирания старых данных. Служба истории буфера cbdhsvc также фигурировала в описаниях уязвимостей повышения привилегий, что делает своевременное обновление системы дополнительным фактором защиты содержимого, временно хранящегося в памяти. Практический вывод простой: копировать пароли, ключи доступа и номера карт стоит с пониманием того, что эти данные какое-то время буквально лежат открытым текстом в оперативной памяти компьютера и потенциально доступны любому процессу, работающему в той же пользовательской сессии.
Менеджеры паролей отчасти учитывают эту особенность и через некоторое время после копирования сами вызывают EmptyClipboard, чтобы принудительно затереть буфер новым пустым значением и сократить окно уязвимости. Программное затирание самого буфера не решает вопрос полностью, потому что физическая страница оперативной памяти, где раньше лежали чувствительные данные, может быть возвращена системой в общий пул и на короткое время остаться нетронутой, прежде чем ее содержимое перезапишет другой процесс. Именно этот эффект и используют инструменты криминалистического анализа: они ищут в дампе оперативной памяти характерные заголовки структур BITMAPINFO или сигнатуры кодировки UTF-16, чтобы восстановить фрагменты давно очищенного буфера обмена.
Буфер обмена выглядит для пользователя как невидимая мелочь между операциями копирования и вставки, но за этой простотой скрывается целая цепочка системных вызовов, десяток параллельных форматов одного и того же фрагмента и отдельная фоновая служба, обслуживающая историю. Понимание того, что все это происходит именно в оперативной памяти, а не на диске, объясняет и скорость вставки, и то, почему скопированные данные исчезают после выключения компьютера, и то, почему к содержимому буфера стоит относиться так же осторожно, как к любым другим незашифрованным данным в памяти процесса.