Qt: quint64, сектор и жопа (14.08.2025). |
![]() |
2025 - Август | |
14.08.2025 11:29 | |
Пусть есть 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 ) |