" title="Написать письмо">Написать письмо
Донаты на карту ВТБ:
2200 4002 2461 6363

Статистика

Пользователи : 1
Статьи : 2223
Просмотры материалов : 8384742
 
Qt: quint64, сектор и жопа (14.08.2025). Печать E-mail
2025 - Август
14.08.2025 11:29
Save & Share
Чем отличилась Qt производства Великобритании: насоздавали своих классов. Не String, а QString; не int64, а qint64, - и утверждалось, что это классы-синонимы по своему функционалу и структуре. Ну вот и досоздавались: это не так. Astra Linux SE v.1.7.4.0(7) и Qt v.5.15.2: недружественные к IT-специалисту ОС и среда разработки - привели к очередным танцам с бубном: при работе с жёстким диском, минуя файловую систему.


Пусть есть QDataStream. Успешно в файл записывается большое число, quint64: 18.446.743.798.831.644.672. После закрытия файла, открытия файла, чтения потоком - успешно и корректно читается.

Между тем, начав читать данные вне файловой системы (секторы жёсткого диска), при помощи QByteArray, - исходное число никак не находилось:
- даже после преобразования QByteArray.toHex().toULongLong(&bOk, 16) - с которым пришлось изрядно попотеть при создании и удостовериться, что конструкция работает как надо;
- грешил именно на ошибки в чтении: сектор мог представлять не 512Б, а 517Б (+4Б на контрольную сумму сектора и что-то в начале ещё есть из служебной информации);
- дополнительно этому мешала зона MFT и загрузочная зона MBR: их чтение не давало возможности даже пытаться определить искомое число в первых секторах носителя.

Далее было принято решение писать в файл много больших чисел, постоянно растущих на единицу (прибавляя к исходному числу в цикле):
- чтение дало повторяющийся результат: из 512Б сектора читалось 3 числа, больше искомого, в постоянных местах сектора (условно, 88-й, 120-й и какой-то там ещё номера байтов). Тоже какая-то дичь - но уже лучше;
- укрепляется мысль, что проблема в алгоритме чтения, - и среди прочего дело не в LittleEndian и BigEndian.

Это мнение было ровно до тех пор, пока не дошло посмотреть записанные биты в файл с помощью HEX-редактора HxD в Windows:
- редактор имеет удобное представление битов в привычные типы данных;
- тут-то шок и настал. uint64 (без q): вместо 18446743798831644672 - было 18446743936270598144 (FF FF FF E0 00 00 00 00);
- без HEX-редактора эту незначительную разницу чисел, близкую к триллиону, глазами видно не было при просматривании файла, например, в Vim.

Поток QDataStream, независимо от указываемой версии с помощью .setVersion(QDataStream::Qt_x_xx): записывает q unsigned int 64 - неправильно. Эта же ошибка имеется при считывании - поэтому никак не ощущается, пока используешь идентичные механизмы записи и считывания (потоком). Из этого также следует, что если файл потом будет считываться другим языком программирования, - может наступить жопа.

Посмотрев на всё это дело, было приняты радикальные решения:
- почти полностью заполнить жёсткий диск одним файлом со 125.012.049.920 уникальными записанными quint64 с разницей в единицу (не затрагивая зону MFT). Тут Astra вставляет свои 5 копеек багов: с драйвером ntfs3 жёсткий диск не заполняется до конца, оставляя 6400КБ свободного места, которое невозможно записать даже во fly-fm и текстовыми редакторами (при этом, если в Windows открыть - можно продолжить забивать диск до отказа, насоздавав файлов или копируя чего). Переключение на старый драйвер ntfs: замедлило скорость жёсткого диска до ~30МБ/с - но баг с заполнением ушёл, и диск забился до отказа;
- считывать так же потоком: открыв само устройство /dev/sda - как файл только для чтения;
- не привязываться к размеру сектора (он всегда делится на 8). Тупо читать 125.025.247.232 раза по 8 байтов, исходя из размера носителя;
- где-то на трехмиллионной итерации: сработало условие, что число >= 18446743798831644672. Не показатель - однако такие числа стали увеличиваться на 1, с увеличением итерации на 1. Значит, чтение происходит корректно: попал в сектор близко к физическому началу диска, являющийся частью кластера ФС ближе к виртуальному концу файла (фрагментацию виртуальных кластеров по физической поверхности диска - никто не отменял). И, в рамках всех 64КБ кластера (состоящего из 128 последовательно идущих секторов): числа точно увеличиваются на 1 - начиная с начальных 8 байтов.

Ещё тест будет вне темы: попытаться в Astra забить весь диск 1ТБ целиком, вместе с полным затиранием зоны MFT. Однако это далеко не конец: нужно убедиться, что все числа уникальные и в наличии на диске вне ФС. Значит, потребуется массив bool размерностью >125.025.247.232 (ещё есть загрузочная зона MBR, её бы посмотреть отдельно) - и где-то надо взять 128ГБ RAM. Или организовать чтение диска 8 раз подряд, анализируя числа массивами по 16ГБ, - при условии наличия 16ГБ RAM (а значит, SWAP будет использоваться по-полной - что ещё более замедлит анализ).
Обновлено ( 14.08.2025 13:05 )
 
 

Последние новости


©2008-2025. All Rights Reserved. Разработчик - " title="Сергей Белов">Сергей Белов. Материалы сайта предоставляются по принципу "как есть". Автор не несет никакой ответственности и не гарантирует отсутствие неправильных сведений и ошибок. Вся ответственность за использование материалов лежит полностью на читателях. Размещение материалов данного сайта на иных сайтах запрещено без указания активной ссылки на данный сайт-первоисточник (ГК РФ: ст.1259 п.1 + ст.1274 п.1-3).

Много статей не имеет срока устаревания. Есть смысл смотреть и 2011, и даже 2008 год. Политика сайта: написать статью, а потом обновлять ее много лет.
Рекламодателям! Перестаньте спамить мне на почту с предложениями о размещении рекламы на этом сайте. Я никогда спамером/рекламщиком не был и не буду!
Top.Mail.Ru