Как найти необъяснимые незаполненные области в сегментах данных:
Я знаю, что это нелегкий способ, но я знаю что он будет работать, поскольку я
делал это сам. Используйте DCC.EXE, компилируйте ваш полный проект (DPR) и
добавляйте к командной строке опцию /GD, это позволит создать .MAP-файл.
MAP-файл создан по правилам форматирования текстового файла, поэтому вы можете
затем загрузить его в Delphi и там изучать.
Первая секция каждого MAP-файла включает в себя все модули, добавленные
линковщиком в EXE-файл и размер этих модулей в HEX-байтах. Имя последнего модуля
в списке - всегда DATA для сегментов данных. Здесь необходимо запомнить одну
вещь - начальный адрес сегмента данных.
Следующая секция MAP-файла является листингом ВСЕХ Public-объявлений.
Публичные объявления включают в себя переменные (например, TForm), возвращаемые
величины и каждый объект, определенный в VCL. Наиболее важные здесь элементы
списка - определения всех переменных в программе и насколько они большие
(устанавливается косвенно).
Самый минимально-возможный проект Delphi создаст вам список из нескольких
сотен записей.
Для нашего примера я использовал пустой проект, который Delphi создает вам
автоматически: сохраните проект и модуль под любым именем каким вы хотите,
закройте проект и выйдите из Delphi. Я использую имена DATAP.DPR и DATAU.PAS.
В DOS-строке введите следующую команду: DCC DATAP.DPR /GD Теперь у вас будет скомпилированный проект и
созданный файл DATAP.MAP. Снова загрузите Delphi и откройте в нем MAP-файл.
Смотрим адрес сегмента DATA. 0008:0000 0E34H DATA DATA В нашем примере, как вы
можете увидеть, VCL требует минимум $0E34 (3636) байт для сегмента данных (Data
Segment). Теперь перейдем ко второй секции (ниже по тексту) и увидим начальные
адреса вашего сегмента DATA. 0008:055A CreationControl
0008:055E VBXHook
....... .......... В любом проекте, который я когда-либо
создавал, первые $0040 байт в MAP-файле всегда резервируются чем-то
неопределенным. Вставляемая по умолчанию часть листинга всегда начинается с
"CreationControl".
В проектах, где я имею хотя бы одно объявление TYPED CONST DATA, всегда
указывается первый начальный адрес с отступом xxxx:0040 и перед
"CreationControl", который, оказывается, сам занимает около 1300 байт.
Используя шестнадцатиричный адрес в качестве указателя, вы запросто можете
вычислить разницу между распределенной памятью и памятью, реально занимаемую
каждым элементом. Для этого понадобиться научный калькулятор, для этой цели
подойдет калькулятор, поставляемый с Windows 3.0, только не забудьте переключить
его в режим scientific (научный). Продолжаем: "встроенные" данные обычно
начинаются с "CreationControl"/"HaltVector", который тут же сопровождается
переменным указателем на вашу главную форму (4 байта). 0008:09DC HaltVector
0008:0A32 Form1
0008:0B60 NewStyleControls
....... ..........
0008:0D84 LongDayNames Все переменные для каждой формы приведены
здесь в том же порядке, как они объявлены в модуле. Строка с "NewStyleControls"
обычно знаменует конец секции с вашими переменными и начало остальных
"встроенных" данных, которые, обычно, заканчиваются строкой "LongDayNames".
Я надесь что мое спутанное повествование не отпугнуло вас от дальнейшего
изучения этого интересного вопроса, по крайней мере вы увидите своими глазами
ваш проект "изнутри" и то, как Delphi "начиняет" EXE-файл данными из вашего
проекта. Далее вы без труда можете найти место, где сегмент данных содержит по
непонятной причине незаполненные области, хотя все это по-прежнему только в
познавательных целях...
- Dennis Passmore |