Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

Работа с памятью. ( Выравнивание )


Страницы:   1 2

Riply ©   (2008-03-20 21:50:00) 

Здравствуйте !
Допустим у нас есть очень привиредливая процедура:

procedure Fastidious(pAligned: Pointer);

Вот подавай ей на входе pAligned выровненный по границе SizeOf(Int64)
иначе она и работать откажется.
И пытаемся мы ее вызвать тремя способами:

procedure TestCallFastidious(pNotAligned: Pointer);
var
//......
MyRecord: TMySuperPuperRecord;
pTmp: Pointer;
begin
//.......  1-й вызов
Fastidious(@MyRecord);
//.......  2-й вызов
pTmp := GetMemory(MemSize);
Fastidious(pTmp);
//.......  3-й вызов
Fastidious(pNotAligned);
end;


Как лучше выкрутиться ?
Для 1-ого и 3-го приходит в голову только
Заводить доп. переменную Pointer и мучаться с перевыделением и копированием.
Со вторым вызовом тоже не понятно.
Мне не удалось получить pTmp не выровненный по 8-байтной границе
и не удалось нигде найти утверждения, что он будет выровнен.
Как с ним обстоят дела ?

P.S.
Пользоваться чем-то вроде VirtualAlloc не хотелось бы.


tesseract   (2008-03-20 23:31:00) [21]


> Компилятор может поместить отдельную Filler в пару регистров
> или выкинуть его совсем, а в случае записи он вряд ли догадается
> соптимизировать.


навряд-ли в регистры - он их 32-х считает (Delphi) а int64, как факт, ещё с первых пней идёт.


palva   (2008-03-20 23:27:00) [22]


> Вот досада :) Как же тогда исхитриться и объявить "ровно"
> ?

Если palva ©   (20.03.08 22:21) [2] не подойдет.
то можно исхитриться с промежуточной процедурой на ассемблере.
Где нужно объявить данные? Глобально или в процедуре?


guav   (2008-03-20 23:20:00) [23]

> var
> Filler: Int64;
> YouParameterData: TFoo;

Если способ с Filler работает, предлагаю
var
 R: record
   Filler: Int64;
   YouParameterData: TFoo;
 end;
Компилятор может поместить отдельную Filler в пару регистров или выкинуть его совсем, а в случае записи он вряд ли догадается соптимизировать.

__declspec(align(8)) в Deplhi насколько я знаю нет, есть $ALIGN но это немного не то.

Насчёт второго случая я за [2] или VirtualAlloc.
Насчёт третьего - можно проверить выравнивание, если неправильное, выделить новый буфер, из которого/в который копировать, и свести ко второму.


Riply   (2008-03-20 23:12:00) [24]

>  [15] palva ©   (20.03.08 23:09)
> Ну значит мне так везет. Я всегда был неудачником :(

Вот досада :) Как же тогда исхитриться и объявить "ровно" ?


tesseract   (2008-03-20 23:11:00) [25]


> palva ©   (20.03.08 23:09) [15]


Выравнивание 8 байт. Или я что-то не понял ?


palva   (2008-03-20 23:09:00) [26]


> Предлагается пробовать до первого отрицательного ? :)

Ну значит мне так везет. Я всегда был неудачником :(
{$APPTYPE CONSOLE}
var
Filler: Int64;
YouParameterData: Int64;
begin
 WriteLn(Integer(@Filler));           //    4216412
 WriteLn(Integer(@YouParameterData)); //    4216420
end.


tesseract   (2008-03-20 23:05:00) [27]


> Допустим, я 10 000 раз получила результат, что выровненно.


Win64 - это в принципе 2 среды. Одна 32 бита, вторая 64. И я не уверен что WoW пропустит вызов внутреннего API, через эмулятор. У меня на Win64 вирусы опознаються по ошибкам записи в память.


Riply   (2008-03-20 23:02:00) [28]

> [11] Игорь Шевченко ©   (20.03.08 23:00)
> Потому что компилятор размещает данные в порядке объявления.

Тогда, почему первое объявление (Filler: Int64;) выровнено ?


Игорь Шевченко   (2008-03-20 23:00:00) [29]

Riply ©   (20.03.08 22:51) [8]

Потому что компилятор размещает данные в порядке объявления.


Riply   (2008-03-20 23:00:00) [30]

>  [10] palva ©   (20.03.08 22:57)
> Нельзя быть уверенной. Вы больше пробуйте, пробуйте...

Допустим, я 10 000 раз получила результат, что выровненно.
Но ведь это ничего не докажет. (Правда один отрицательный докажет :)
Предлагается пробовать до первого отрицательного ? :)


palva   (2008-03-20 22:57:00) [31]


> А почему, при таком объявлении, можно быть уверенной, что
> YouParameterData выровнена ?
>

Нельзя быть уверенной. Вы больше пробуйте, пробуйте...


tesseract   (2008-03-20 22:55:00) [32]


> Стандартный GetMem вроде выделяет выровненную память, если
> мне память не изменяет.


Win64 - выделяет выровненную по 4,  если не Define-нить.


> Дело в том, что проверка производилась под Win64 (не мною).


Он линейкой проверял ?  И именно  WoW обошёл ?


Riply   (2008-03-20 22:51:00) [33]

> [1] Игорь Шевченко ©   (20.03.08 22:12)

> var
>  Filler: Int64;
>  YouParameterData: TFoo;

А почему, при таком объявлении, можно быть уверенной, что YouParameterData выровнена ?


Riply   (2008-03-20 22:42:00) [34]

> [5] palva ©   (20.03.08 22:29)
> Господь с вами!

Спасибо. Значит я плохо пыталась :)


Riply   (2008-03-20 22:40:00) [35]

> [3] Игорь Шевченко ©   (20.03.08 22:25)
> 3-ий способ - ругаться, если приходит извне. Как собственно NT ругается

STATUS_INVALID_PARAMETR

Но, Игорь, это не совсем точно :)
Дело в том, что проверка производилась под Win64 (не мною).
Это самый вероятный вариант, где я спотыкаюсь.
Я излазила MSDN, и единственное объяснение, которое нашла это
данная ошибка при вызове NtQueryInformationFile(...FileStreamInformation...).
Проверить не могу так как у меня нет доступа к Win64


palva   (2008-03-20 22:29:00) [36]


> Мне не удалось получить pTmp не выровненный по 8-байтной
> границе

Господь с вами!

{$APPTYPE CONSOLE}
var
 i1: Pointer;
 i2: Pointer;
 i3: Pointer;
begin
 i1 := GetMemory(4);
 i2 := GetMemory(4);
 i3 := GetMemory(4);
 WriteLn(Integer(i1)); // 8585220
 WriteLn(Integer(i2)); // 8585232
 WriteLn(Integer(i3)); // 8585244
end.


Игорь Шевченко   (2008-03-20 22:26:00) [37]


> Со вторым вызовом тоже не понятно.


Стандартный GetMem вроде выделяет выровненную память, если мне память не изменяет.


Игорь Шевченко   (2008-03-20 22:25:00) [38]

3-ий способ - ругаться, если приходит извне. Как собственно NT ругается


palva   (2008-03-20 22:21:00) [39]

Выделить на 8 байтов больше чем надо, а потом выровнять.


Игорь Шевченко   (2008-03-20 22:12:00) [40]


> Вот подавай ей на входе pAligned выровненный по границе
> SizeOf(Int64)
> иначе она и работать откажется.
> И пытаемся мы ее вызвать тремя способами:


var
 Filler: Int64;
 YouParameterData: TFoo;


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо