Карта сайта Хакер в RSS Энциклопедия Хакера PDA версия сайта Почтовые рассылки Хакера    Хакер в Twitter Хакер в ВКонтакте Приложение Хакер для Facebook Хакер на Formspring.me
Журнал Новости Форум Видео Life Xakep Live (блоги)
Bugtrack Статьи Блог Поиск English
Итоги конкурса Group-IB Итоги конкурса Group-IB
Настало время подведения итогов нашего конкурса, который мы проводили совместно с компанией Group-IB, специализирующейся на расследовании инцидентов информационной безопасности....
Трюки с phpinfo Трюки с phpinfo
Совсем недавно в паблике появилась информация о новом интересном подходе к эксплуатации уязвимостей класса LFI с помощью бесполезной на первый взгляд функции phpinfo() и временных загрузочных файлов. Берем на вооружение этот полезный прием....

Упаковка сложных типов данных в Delphi

Bookmark and Share

В этой статье я хотел бы рассказать и показать особенности использования "уплотнения сложных типов данных" в Delphi.

Все когда-нибудь имели дело с записями. Записи используются во многих случаях – для создания файловых справочников, удобной группировки и представления данных, в системном программировании и т.д. Например, открыв файл Windows.pas (стандартный модуль, подключается в разделе uses), можно найти что-то типа такого описания:

_POINTL = packed record
x: Longint;
y: Longint;
end;

или

TISHMisc = packed record
case Integer of //Здесь используется запись с вариантами
0: (PhysicalAddress: DWORD);
1: (VirtualSize: DWORD);
end;

Что же здесь обозначает ключевое слово packed? Слово Packed говорит Delphi минимизировать память. Так что же получается, без этого слова у нас структура занимает памяти больше?

Вот пример записи:

TRecord = Record
pole1 : byte;
pole2 : string[4];
pole3 : integer;
pole4 : Int64;
end;

Давайте подсчитаем ее размер: pole1 – 1 байт, pole2 – 5 байт (надеюсь, не забыли 4 байта под символы и 1 под размер), pole3 – 4 байта, pole4 – 8 байт. Если их сложить получиться 18 байт. Давайте проверим:

size1 := sizeof(TRecord);
ShowMessage(‘Размер обычной записи = ’+IntToStr(size1));

Результат: 24.

Удивлены? А теперь добавьте слово packed перед словом Record… Размер 18 как и подсчитали ранее. Так куда же у нас пропали целые 6 байт?! А если у нас будет массив из 10 000 000 таких записей, например в каком-нибудь справочнике, мы потеряем около 57 Мегабайт?

Давайте разберемся, почему так происходит. Для этого я использовал встроенный дизассемблер в Delphi. На форму кидаем кнопку и на обработчик нажатия пишем:

procedure TForm1.Button1Click(Sender: TObject);
type
// обычная запись
TRecord = Record
pole1 : byte;
pole2 : string[4];
pole3 : integer;
pole4 : Int64;
end;
// упакованная записи
TPackedRecord = Packed record
pole1 : byte;
pole2 : string[4];
pole3 : integer;
pole4 : Int64;
end;

var
Rec : TRecord;
packedRec : TPackedRecord;
size1 : integer;
begin
ShowMessageFmt('Adress = %P',[Addr(Rec)]); //Вывод адреса нашей записи
size1 := sizeof(Rec); //Узнаем размер
// присваиваем некоторые данные нашей записи
Rec.pole1 := $FF;
Rec.pole2 :='hack';
Rec.pole3 := $AAAAAAAA;
Rec.pole4 := $1122334455667788;
ShowMessage('Размер структуры = ' + IntToStr(size1)); //выводим размер
end;

Функцию ShowMessageFmt используем для того, чтобы вывести адрес нашей структуры. Обычный ShowMessage не поможет, т.к. нам надо вывести указатель (тип Pointer). Этот адрес меняется, так что у вас может быть другой. Функция Addr – это получение адреса, возвращаемый тип Pointer. Вот ее результат:

Запомним этот адрес. Теперь поставим breakpoint на последнем ShowMessage – нажмем F5 на этой сроке.

Теперь запустим. Программа выдаст сообщение с адресом, а затем остановиться на предпоследней строке. Нажимаем Ctrl + Alt + C. Появится окно дизассемблера. Щелкаем правой кнопкой мыши по левой-нижней области (dump памяти) и выбираем "Идти к адресу".

Вводим наш адрес записи (например так: $0012F568), который получили с помощью ShowMessageFmt, и попадаем на адрес начала нашей структуры.

Помним, что pole1 мы присвоили значения $FF (т.е. =255), pole2 =’hack’, pole3 = $AAAAAAAA (4 байта, т.е. =2863311530) и т.д. Посмотрим на рисунок, на нем я отобразил структуру байтов и как они расположены в памяти.

Как видим, после данных pole2 идут байты выравнивания, которые выравнивают границу памяти до 8 байт. И поэтому Pole3 начинается с адреса кратному 8. То же самое видим и с Pole4 – сначала выравнивается граница (байты 0E 00 00 00), а затем идут сами данные (хочу заметить, что в памяти данные хранятся в обратном порядке, что видно в Pole4).

А теперь проверим упакованную запись. Переменную Rec заменяем в коде на packedRec, т.е. используем packed record. И проделываем все то же самое:

Здесь видим, что никаких байт выравнивания нет, а все данные (поля) расположены друг за другом – упакованы.

Возможно возник вопрос: почему в первом примере данные выравнивались по границе 8 байт? Все дело в настройках компилятора. Если вы откроете Project – Option – Compiler (опции компилятора), то там будет списочек Record field alignment, в котором можно выбрать нужное выравнивание (8,4,2 или 1 байт). Не забываем перекомпоновать проект после изменений. Кстати выравнивание по 1 байту и есть упаковка данных.

Второй вопрос: почему же всегда не упаковывать данные? К сожалению, упаковка данных имеет не только плюсы, но и минусы. Так, например, не выравнивая границу мы увеличиваем время доступа к полям. Поэтому использовать упаковку надо с умом.

Кстати, в том же файле Windows.pas можно найти не только упаковка записей, но и массивов, вот пример:

CprMask: packed array[0..3] of DWORD;

Попробуйте сами проанализировать упаковку этого массива.



Теги: Delphi , программирование





СЛЕДУЮЩИЕ СТАТЬИ
Ударь копирайтом по работодателю: возвращаем финансы, честно заработанные на служебных произведениях
Руткит в сетевухе: фантазии программиста о создании непобедимого руткита
Чемпионаты по программированию и не только
Алгоритмическая симфония из одной строчки кода
Kinect: разбираемся с новым девайсом и учимся писать для него приложения
Программное обеспечение: поглощая мир
SMS-похититель для Android: Sсriрting Layer for Android - интересная среда разработки для мобильного телефона
13 утилит для безопасной разработки: инструменты от Microsoft для написания надежного кода
Silverlight: защита и нападение
Кроссплатформенный кодинг для мобильных платформ: покоряем iOS, Android, Bada, Symbian и WM с помощью AirPlaySDK
ПРЕДЫДУЩИЕ СТАТЬИ
KIS 2010: версия новая, баги старые
Windows 7 для разработчика: технологические нововведения в новой ОСи
Global Positioning Trojan: следим за местоположением жертв продвинутого телефона
Термальная угроза: мифы и реальность №2
Разработка виджетов в Windows Mobile 6.5
Конь в яблоках: пишем троян для Apple iPhone
Термальная угроза: мифы и реальность №1
Куда податься телефонному кодеру: полный гид по мобильным платформам для программиста
Проникновение в BIOS ROM: осваиваем SPI Flash №2
Проникновение в BIOS ROM: осваиваем SPI Flash №1
ОБСУЖДЕНИЕ СТАТЬИ
Логин:
Пароль:
Если у вас есть форумный логин - вы можете использовать его, иначе анонимный гостевой доступ.

Для оставления комментария вы можете зарегистрироваться по упрощенной процедуре.

Обсуждение этой статьи на forum.xakep.ru
Для отправки сообщения введите код, указанный на картинке
Сообщение

UserГость
20.10.2009 18:14:10
Ответить Ссылка
Отличная статья. Хоть немного научит новичков пользоваться дизассемблером, а то привыкли накидать кнопок в design-time и мнет себя крутыми программистами.
UserГость
20.10.2009 22:55:38
Ответить Ссылка
побольше таких статей
UserГость
20.10.2009 23:39:07
Ответить Ссылка
Делфи мёртв. Не тратьте время, учите нормальные языки.
Avatar=OutlaW=
21.10.2009 8:01:35
Ответить Ссылка
quote:

Делфи мёртв. Не тратьте время, учите нормальные языки.

Кто сказал "мяу"?
UserГость
21.10.2009 15:06:16
Ответить Ссылка
делфи мертв? скажи это моему преподу по программированию
UserГость
21.10.2009 15:14:42
Ответить Ссылка
"Делфи мёртв. Не тратьте время, учите нормальные языки." - и что по твоему нормальные языки, а что нет? или мы по моде шагаем?
Для каждых вещей выбирается конкретный язык, это конечно то, что касается профессионалов, а не ньюби как ты.
К тому же он еще не умер, так как каое никаое развитие, но есть.
Давно ли ты видел развитие Perl? это мертвый язык? то-то же
UserГость
21.10.2009 15:16:23
Ответить Ссылка
"делфи мертв? скажи это моему преподу по программированию" - а при чем тут преподы вообще? ты для преподов будешь писать проги всю жизнь?
Для многих преподов жизнь еще остановилась на турбо паскале.
AvatarD. Scandal
21.10.2009 17:13:53
Ответить Ссылка
И снова унылая возня вокруг Делфи. Задета славянская гордость могущественных делфи-кодеров.
Старый пес ваш давно издох, уважаемые.

Я понимаю, что совсем дохлый он будет только в том случае, когда прекратится его разработка, но он очень болен. Очень.
User][aKER_теоретик
21.10.2009 17:22:33
Ответить Ссылка
У него предсмертные конвульсии.
UserГость
21.10.2009 16:37:53
Ответить Ссылка
Статья пустяковая, даже новичку который прочел хелп понятно что в record секции выравниваются по 4 байта. Если включить packed. То они выравниваются по количеству данных которые там расположены.
UserГость
22.10.2009 7:44:24
Ответить Ссылка
Меня пробила реальная ностальгия по Delphi и по его синтаксису. Сейчас, когда я уже отработал около 9 лет на C#, как и Андерс Хейльсберг я с Delphi на C# перешел :), я с удовольствием вспомнил старый добрый Паскаль...
Всё конечно хорошо, но такие статьи нужны были эдак лет 10-15 назад, а сейчас это уже не актуально. Сейчас нужно учить .NET и писать статьи о Delphi.NET .
UserГость
22.10.2009 9:44:52
Ответить Ссылка
Дельфи мертв....
"Ты еще скажи что знаешь где он похоронен, а С++ плачет на его могиле"
UserГость
22.10.2009 16:25:48
Ответить Ссылка
Статья действительно не актуальная уже. Но однозначно сказать, что delphi мертв врядли можно... Пока этот инструмент используется, пока embarcadero занимается разработкой и он для них рентабельный, delphi не мертв. Другое дело, что не перспективный.
UserГость
22.10.2009 16:59:55
Ответить Ссылка
Ну да, конечно же ваш убогий мелкомягкий C# рулит!

Сам пишу на С++ (ушел с делфи достаточно давно, но иногда приходится писать на нем), но покажите-ка мне хотя бы один рабочий компонент для ICQ? Не знаете ни одного? А для делфи есть как минимум 2. И так во многом.
UserГость
22.10.2009 17:07:09
Ответить Ссылка
Я уже говорил, что главный идеолог Delphi, Anders Heilsberg перешёл в Microsoft. Там он использовал свой опыт и создал C#. Сама структура этого языка очень похожа на Delphi.Но помимо этого ещё есть .NET Framework, который является мощным дополнением к любому языку. Даже на Fortran, а не только на Delphi можно писать используя его. Но когда используешь фрэймеворк, то язык "теряется" как таковой. Скажем, VB.NET, это уже не тот VB 6, а MC++, это уже не тот, хорошо знакомый VC++. Так что, когда тут кто-то сказал, что Delphi мёртв, это было не так далеко от истины. И вообще, Borland, уже на грани смерти. В агониях примерно с 2005 года. Они выпустили Together и после этого больше ничего про их продукцию не слышал. Если у кого другие сведения, плиз, поделитесь.
UserГость
22.10.2009 17:24:51
Ответить Ссылка
И вообще, я смотрю, что люди не только в бывшем СНГ, но и тут, у нас в Торонто слабо знают последние технологии Microsoft. Да... эта компания монополист, но никакие Linux-ы, Unix-ы ещё не предложили ни одного аналога для MVC, для LINQ, для ADO.NET Entity Framework.
Хотя следующие технологии имеют аналоги, они не имеют такой языковой поддержки, как в .NET :
1. WPF
2. SilverLight
3. WF
4. WCF
Найдите это всё на сайте Microsoft и у вас сомнений не останется в том, что Delphi - мёртв!!!
UserГость
23.10.2009 14:37:30
Ответить Ссылка
Я профессионал. Про мёртвый язык, это был всего лишь добрый совет. Хотить батрачить за копейки на поддержка устаревших проектов - учите делфи.

Хотите нормально работать и развиваться, учите нормальные языки С++, C#, Java и т.д.
UserГость
23.10.2009 15:17:07
Ответить Ссылка
Статья раздута конечно. Всё это можно было выразить в паре предложений.

Delphi пока еще не мёртв. Этот язык хорош тем, что он на стороне программиста. Никто не пишет абсолютно безошибочного кода, и Delphi своей структурой и синтаксисом помогает их избегать. Конечно можно и на нём натворить делов, конечно он тоже не идеален.
Теперь посмотрим на C++. Главный плюс: С++ - это стандарт. На нём пишут все и для всех платформ. Просто огромная армия программистов каждый день прямо или косвенно развивает и поддерживает C++. Delphi в этом плане конечно же трудно соперничать с во много раз превосходящей армией сиплюсплюсников.
На этом преимущества C++ заканчиваются. Как программист с 12-тилетним стажем скажу, на C++ трудно программировать. Еще труднее программировать без багов, потому что язык многое прощает, что прощать не должен. Посмотрите сайты, блоги, посвящённые C++: половина статей будет на тему "угадайте, что делает эта замысловатая конструкция C++?" Почитайте Страуструпа об истории создания C++: почти в каждой главе он признаётся, что он принял некрасивое и нелогичное решение, потому что ему нужно было достичь совместимости с оригинальным C.
Хотите каждый день бороться с языком, пользуйтесь C++.
Переходите на платформу .NET, если вы хотите до конца жизни быть привязанными к одной платформе. Да я в курсе про MONO и прочее, но как только альтернативные реализации добьются полной совместимости, Microsoft выпустит новую версию, новый стандарт, и всё нужно будет начинать сначала.
UserГость
24.10.2009 13:43:45
Ответить Ссылка
Delphi, C++... C + Python --- вот наше светлое будущее!
UserГость
24.10.2009 15:07:36
Ответить Ссылка
D. Scandal Отправлено: 21.10.2009 17:13:53

Соси хуй ! Шлюха !
UserГость
24.10.2009 16:48:05
Ответить Ссылка
Я немогу вас понять как можно сравнивать язык программирования и среду разработки. Eсли так то надо сравнивать Delphi vs Visual C++
UserГость
24.10.2009 20:19:33
Ответить Ссылка
Object Pascal с некоторых пор называется Delphi, а следовательно Delphi - не среда разработки и сравнение более чем корректно.
UserГость
24.10.2009 21:59:54
Ответить Ссылка
Вы не правы . Object Pascal являеться языком программирования .
вот ту посмотрите ради интереса.
http://virtualizate.ru/programmirovanie/4-novaya-sreda-razrabotki-delphi-2010.html
Если сравнивать Object Pascal и ООП С++ то С++ лудше.
UserГость
24.10.2009 22:01:23
Ответить Ссылка
Поржал, конечно, что про упаковку структур можно написать столько букав. Похоже в Delphi сложное понятие :)
UserГость
26.10.2009 17:42:49
Ответить Ссылка
Интересно, почему кричат, что C++ "лудше", чем Delphi, только малолетние непрограммеры, которые Delphi видели только на картинке, а на C++ ничего не писали сложнее "Hello, World"?
UserГость
26.10.2009 20:43:35
Ответить Ссылка
У Delphi нет же множественого наследования, использование значении по у молчанию void f(int i=0),нет шаблонов, stl, boost.
UserГость
27.10.2009 1:08:30
Ответить Ссылка
Предыдущему автору:
Современную версию Delphi хоть раз видел?
Множественное наследование - зло. Значения по умолчанию есть. Шаблоны (дженерики) есть. stl, boost etc - мясо нарастёт со временем, сейчас есть библиотеки типа FastCode и т.п.
UserГость
28.10.2009 15:10:54
Ответить Ссылка
>Шаблоны (дженерики) есть

хм... может я что то пропустил, напишите пожалуйста пример!
UserГость
28.10.2009 18:06:50
Ответить Ссылка
"Обобщённое программирование(generics) в Delphi 2009 для Win32":
http://www.tdelphiblog.com/2009/10/generics-delphi-2009-win32.html
UserГость
28.10.2009 18:44:17
Ответить Ссылка
В D7, там то это нет!? Походу это в 2009 появилось только...
UserГость
29.10.2009 4:51:41
Ответить Ссылка
Delphi точно так же как и C# (си с шарфиком) привязывает к определенной платформе.
UserГость
29.10.2009 10:57:30
Ответить Ссылка
И скажите пожалуйста как эта пратформа то называется))? Уж не Intel x86 ли xД ))
UserГость
30.10.2009 2:05:27
Ответить Ссылка
Имелось в виду платформа Windows. Причем только 32-х рарядные.
Kylix умер, толком не родившись.
Кроссплатформенные (в т.ч. 64-х разрядные) компиляторы Delphi - только в далёкой перспективе.
И ещё всё портит цена в 1 тыс. у.е. и отсутствие какой-либо бесплатной лайт версии (устаревшую Turbo Delphi Explorer не считаем). Дома конечно похуй на лицензионность, но на работе глаза на это не будут закрывать.
UserГость
29.03.2010 18:09:10
Ответить Ссылка
ОТЛИЧНАЯ СТАТЬЯ!!!
UserГость
28.10.2010 10:54:36
Ответить Ссылка
Автор статьи утверждает, что "ShowMessage не поможет". Оказывается наоборот: showmessage(IntToHex(integer(Addr(Rec)),8));

P.S. Сишники, идите своей дорогой, а то чуть статья про Делфи, так вы, как черви навозные после дождя, вылазите наружу.
UserГость
09.11.2010 15:51:16
Ответить Ссылка
Отличная статья!
UserГость
31.01.2011 14:49:36
Ответить Ссылка
Эт точно... все только и орут что дельфи - говно... покажите пальцем в чем именно? там нельзя написать то что можно написать в С++?
куча софта написано которым пользуются многие и не брезгуют: totalcommander, qip, thebat, restorator...




Keywords: zPOSTz zHOMEz, zSOFTz, zHOWz, zINFOz, zYANDEXz z49795z
Для Авторов: edit Lock delete Lock



    Rambler's Top100