Delphi скопировать область памяти
← →
DVM © ( 2006-12-28 12:11 ) [0]
Зачем создали две одинаковые функции?
← →Игорь Шевченко © ( 2006-12-28 12:16 ) [1]
Как ты сам понимаешь, вторая функция удаляет старое содержимое памяти
← →DVM © ( 2006-12-28 12:45 ) [2]
> Игорь Шевченко © (28.12.06 12:16) [1]
Вот их исходный код из модуля Windows:
procedure MoveMemory(Destination: Pointer; Source: Pointer; Length: DWORD);
begin
Move(Source^, Destination^, Length);
end;
procedure CopyMemory(Destination: Pointer; Source: Pointer; Length: DWORD);
begin
Move(Source^, Destination^, Length);
end;
Ну как же - процедура Move смотрит, откуда ее вызывают, в зависимости от этого выполняет разные действия.
← →Anatoly Podgoretsky © ( 2006-12-28 13:07 ) [4]
> DVM (28.12.2006 12:11:00) [0]
А справку прочитать не судьба.
← →MBo © ( 2006-12-28 13:08 ) [5]
Два названия - поскольку пара таких функции в platform SDK есть (одна из них не работает с перекрывающимися областями).
← →DVM © ( 2006-12-28 13:24 ) [6]
> Anatoly Podgoretsky © (28.12.06 13:07) [4]
Вы ее сами то читали?
В Delphi справка описывает не совсем эти функции, а одноименные из platform SDK.
> Игорь Шевченко © (28.12.06 13:00) [3]
Вот код Move()
procedure Move( const Source; var Dest; count : Integer );
var
S, D: PChar;
I: Integer;
begin
S := PChar(@Source);
D := PChar(@Dest);
if S = D then Exit;
if Cardinal(D) > Cardinal(S) then
for I := count-1 downto 0 do
D[I] := S[I]
else
for I := 0 to count-1 do
D[I] := S[I];
end;
где она смотрит?
> MBo © (28.12.06 13:08) [5]
Получается одна из функций из Delphi не соответствует своему названию.
Anatoly Podgoretsky © ( 2006-12-28 13:28 ) [7]
> DVM (28.12.2006 13:24:06) [6]
> где она смотрит?
А ты внимательно посмотри.
← →DrPass © ( 2006-12-28 13:33 ) [8]
> DVM © (28.12.06 13:24) [6]
В Delphi VCL/RTL вообще нет этих функций. Там есть одна функция - Move. А CopyMemory и MoveMemory есть в Windows API. Другое дело, что разработчики Delphi посчитали свою реализацию Move более эффективной, чем микрософтовские функции, и заменили их на ее вызов. Естественно, просто убрать обе функции нельзя - иначе потеряется совместимость со старыми приложениями.
DVM © ( 2006-12-28 13:40 ) [9]
> А CopyMemory и MoveMemory есть в Windows API
Их нет в API вроде. Они есть в языке си.
О, может эта, как уж ее, Compiler magic ?
Я знал, я знал! :))
← →DrPass © ( 2006-12-28 13:52 ) [11]
> DVM © (28.12.06 13:40) [9]
> Их нет в API вроде
Есть. Это WinAPI-функции, описаны в winbase.h. Если ты посмотришь этот файл, то увидишь, что они сводятся к вызовам RtlCopyMemory и RtlMoveMemory из ntdll
clickmaker © ( 2006-12-28 13:53 ) [12]
> [9] DVM © (28.12.06 13:40)
>
> > А CopyMemory и MoveMemory есть в Windows API
>
> Их нет в API вроде. Они есть в языке си
winnt.h
NTSYSAPI
VOID
NTAPI
RtlCopyMemory (
VOID UNALIGNED *Destination,
CONST VOID UNALIGNED *Source,
SIZE_T Length
);
RtlXXXMemory живут в ntdll.dll
← →DVM © ( 2006-12-28 13:57 ) [13]
> DrPass © (28.12.06 13:52) [11]
> clickmaker © (28.12.06 13:53) [12]
ясно.
Игорь Шевченко © ( 2006-12-28 14:10 ) [14]
memmove от memcpy отличаются тем, что первая гарантировано переносит область памяти на по указанному адресу без изменений.
← →Sha © ( 2006-12-28 14:16 ) [15]
> Игорь Шевченко © (28.12.06 14:10) [14]
> memmove от memcpy.
Ну вы, блин, даете )) а от сабжевых CopyMemory и MoveMemory ?
← →DrPass © ( 2006-12-28 16:25 ) [16]
> Sha © (28.12.06 14:16) [15]
А от сабжевых тоже ничем не отличаются, если это Win9x/Win32s :)
Sha © ( 2006-12-28 16:34 ) [17]
> DrPass © (28.12.06 16:25) [16]
> А от сабжевых тоже ничем не отличаются
Не может быть, я в шоке :)
Эти две между собой отличаются,
но не отличаются от тех двух,
которые между собой не сильно) отличаются.
Как дальше жить, кому верить?
← →DVM © ( 2006-12-28 16:34 ) [18]
> А от сабжевых тоже ничем не отличаются, если это Win9x/Win32s
По работе может и не отличаются, но я не про них спрашивал.
Джо-со-смарта ( 2006-12-28 16:35 ) [19]
Действительно, как страшно жить! :-)
← →DrPass © ( 2006-12-28 16:47 ) [20]
> Sha © (28.12.06 16:34) [17]
Все нормально, это обычная философская дилемма
Игорь Шевченко © ( 2006-12-28 16:57 ) [21]
Sha © (28.12.06 14:16) [15]
А про сабжевые я в [1] сказал.
← →Sha © ( 2006-12-28 17:05 ) [22]
> Игорь Шевченко © (28.12.06 16:57) [21]
Ну так в [6] паскальная реализация дана, дальше включай мозги :)
Они не услышат, потому что ща в лифте катаются.
При этом, как сообщают "малае костоправы" (© Sha), стоят спиной к двери.
Sha © ( 2006-12-29 09:26 ) [33]
малые костоправы
необходимо реализовать такую штуку:
в произвольное место в памяти записываются последовательно разные данные - числа, текст, отдельные символы.
при этом "курсор" перемещается по мере записывания данных.
память при этом будет выглядеть примерно вот так:
[4 байта] - какое-то число
[1 байт] - 1 буковка
[10 байт] - какое-то слово
и т.д.
данные записываются в место, на которое указывает pointer,
при этом после записи pointer увеличивается на длину записанных данных?
чтобы следующие данных дописывались в конец предыдущих.
написал функцию для записи в память строки.
на входе:
1. указатель на место записи (pointer)
2. строка (string)
в принципе все работает как надо, но хотелось бы услышать мнение знающих людей,
насколько оптимальна такая процедура.
Главный вопрос - есть ли более быстрые функции копирования памяти?
по этой теме нашел функцию move, но что-то она у меня не вызывает доверия.
кривое название, непонятные аргументы, попробовал ее вместо своего кода -
прога работать перестала. Да, знаю как это звучит =). пока особо не разбирался в причинах,
но с моим то кодом все работало, а с move - нет.
т.е. как по аналогии с текстом - можно посимвольно копировать одну строку в другую,
а есть функция Copy, которая вроде как быстрее, потому что реализована на более низком уровне.
по этой теме нашел функцию move, но что-то она у меня не вызывает доверия. кривое название, непонятные аргументы, попробовал ее вместо своего кода - прога работать перестала. |
Действительно, название кривоватое, но это идёт ещё из старого Pascal'я. Но вообще она для данного случая как раз подходит. Что непонятно с аргументами?
т.е. как по аналогии с текстом - можно посимвольно копировать одну строку в другую, а есть функция Copy, которая вроде как быстрее, потому что реализована на более низком уровне. |
функция Copy, делает тоже самое
только она оптимизирована, а ваш цикл нет.
и строки давно уже лучше просто присваивать.
move то что нужно для копирования, но возможно вы не до конца понимаете как лежат данные в памяти или копируете хз куда.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
аргументы функции move:
procedure Move(const Source; var Dest; count:Integer);
по-хорошему компилятор на такой строчке должен выдать синтаксическую ошибку ,
мол "не охренели ли вы не указывать тип данных аргумента".
но нет, все ок, как буд-то так и надо.
не, на практике функция, конечно, принимает pointer'ы,
но это все-таки не дело. по мне так такой интефейс у функции
это такой же плохой тон, как и неинициализированный указатель
хотя, конечно, возможно что я чего-то не знаю,
и такой способ указания аргументов это крутая фишка вроде defaul-свойств,
которая позволяет передавать в качестве параметра переменные любого типа.
впрочем не суть. неуютно =(
Пепел Феникса, по поводу работы памяти - да, не владею в совершенстве,
но в целом представляю. вся память - это набор байт. 1 байт - одна ячейка
указатель - это просто номер ячейки памяти.
если к указателю прибавить 1, то он будет ссылаться на соседнюю ячейку памяти.
память нужно специально выделять.
на более низком уровне все сложнее, если загуглить эту тему,
то узнаешь про страницы памяти, при минимальный блок памяти, кучи и т.д.
но как я понял, память, выделенная под строку представляет собой
монолитный кусок чистых байтов (ключевое слово "монолитный"), правильно?
кстати, ребята с вашего же форума меня и научили, что
лучше сразу выделить необходимую память под строку,
чем увеличивать ее в цикле, поскольку каждое увеличение -
это перекладывание данных на новое место.
если это так, тогда я все делаю правильно =)
по поводу того, что строки нужно присваивать - вообще не врубился к чему это вы))
у меня ведь задача не s1:=s2, и даже не s:=s+IntToStr(i).
задача в том, чтобы в один поток данных сложить разные типы данных.
под число 4 байта - имеется в виду не четырехзначное число, а именно тип integer, который занимает 4 байта.
опишу контекст, в котором работаю:
есть таблица, допустим StringGrid, но это не суть.
главное что есть сетка строк - двумерный массив.
надо все это сохранить в файл. как?
еще один вариант - придумать определенную структуру хранения данных в файле.
я решил сделать так:
данные хранятся в виде блоков.
первый байт блока - его тип
потом четыре байта - длина блока
далее содержимое блока.
соответственно алгоритм чтения:
1. читаем первый байт
2. читаем 4 байта - получаем длину блока
3. читаем контент - указанное кол-во байтов
благодаря тому, что здесь не надо сравнивать каждый символ,
а время тратится в основном на копирование данных,
75-метровая таблица грузится за 2 секунды, что гораздо приятнее десяти =)
память под поток данных выделяю с помощью строки: SetLength(s,100500);.
указатель: p:=@s[1]; на первый символ строки.
этот указатель и передается в мои функции WriteString, WriteInteger, WriteByte,
а так же в аналогичные для чтения.
вот, например, ReadInteger:
в принципе везде одна и та же операция - копирование памяти с места на место.
Пепел Феникса, что тут еще можно оптимизировать?
AllDer ( 2004-01-16 01:01 ) [0]
понял,возник вопрос написать свою
CopyMemoryEx,но даже CopyMemory немогу написать
в Dll system искал - ненашел чтоб dizассемблить.
собственно CopyMemory(Dest,Source:pointer;Length:dword)
источник и приемник и длина.
парился с
procedure ImitationCopy(Start,Finish:poiter;Len:dword);
var
a:dword;
begin
for a:=0 to len do begin
asm
push start
pop a
inc a // +1
push a
pop start
push finish
pop a
inc a // +1
push a
pop finish
end;
Finish:=Start; // присваиваем
<
Но здесь видать по адресу Finish содержимое не меняется,меняется лишь
указатель на ту ячейку и указатель затирается следующим for^ом>
b:^byte;\ byt:byte;\ c:pointer;
c:=Start; // copy pointer
b:=c; // copy в типиз указатель
byt:=b^; // отбираем байт
Finish:=b;//его присваваем
end;
>
Где взять исходник CopyMemory() ?
VMcL ( 2004-01-16 01:20 ) [1]
Посмотри System.Move.
← →AllDer ( 2004-01-16 01:23 ) [2]
А что это System.Move?
есть API func MoveMemory
VMcL ( 2004-01-16 01:36 ) [3]
А есть Delphi"s Move. F1.
← →VMcL ( 2004-01-16 01:38 ) [4]
Насчет исходника CopyMemory: вставь в Delphi-прогу вызов CopyMemory и отладчиком. Но я бы брал всё-таки Move.
← →AllDer ( 2004-01-16 01:42 ) [5]
procedure Move(const Source; var Dest; Count: Integer);
а она с pointer^ми работает?проверю
A: array[1..4] of Char;
B: Integer;
begin
Move(A, B, SizeOf(B)); < SizeOf = safety! >
end;
Andy BitOff ( 2004-01-16 03:24 ) [6]
procedure TForm1.Button1Click(Sender: TObject);
var FromMem,ToMem:Pointer;
Size:Integer;
begin
asm
push edi
push esi
mov esi,[FromMem]
mov edi,[ToMem]
mov ecx,[Size]
repne movsb
pop esi
pop edi
end;
end;
AKul ( 2004-01-16 13:23 ) [7]
> AllDer (16.01.04 01:01)
> for a:=0 to len do begin
> asm
> push start
> pop a
> inc a // +1
> push a
> pop start
>
> push finish
> pop a
> inc a // +1
> push a
> pop finish
> end;
> Finish:=Start; // присваиваем
Не в обиду будет сказано, но что это за бред? Кто тебя на ассемблере учил программировать? Что это за алгоритм такой?
Если перевести это на Delphi, то выглядеть будет приблизительно так:
for a:=0 to len do begin
a:=Start+1; //Зачем здесь ипользовать переменную цикла?
Start:=a;
a:=Finish+1;
Finish:=a;
Алгоритм на Delphi должен быть бризительно следующий:
procedure Copy(var Src,Dest;Count:integer);
Type ArrayType=Array [0..$7FFFFFFE] of byte;
var i:integer;
S,D:^ArrayType;
begin
S:=@Src;D:=@Dest;
for i:=0 to Count do
D^[i]:=S^[i];
end;
При вызове CopyMemory Delphi вызывает не API-функцию с таким именем, а свою, исходный код которой можно найти в Windows.pas:
procedure CopyMemory(Destination: Pointer; Source: Pointer; Length: DWORD);
begin
Move(Source^, Destination^, Length);
end;
Что касается исходного кода API-функции CopyMemory, то он приблизительно такой, как написал Andy BitOff © (16.01.04 03:24) [6] (за исключением того, что следует обнулить флаг направления копирования данных (cld) и он оптимизирован - копируются не байты, а двойные слова).
Еще, CopyMemory (API) используется только не для перекрывающихся диапазонов! Для перекрывающихся диапазонов следует использовать MoveMemory.
← →mrcat ( 2004-01-16 13:28 ) [8]
>Andy BitOff © (16.01.04 03:24) [6]
>repne movsb
на 32-х битных не оптимально, гораздо быстрее в купе с repne movsd
Тимохов ( 2004-01-16 13:53 ) [9]
Хочу сказать, имхо:
Моve быстрее чем api функции. Проверял.
а Move определено в system.pas
Разобраллся . Спасибо
Осталось присабачить,чтоб в чужих процессах
могло пахать.
Тема ЗАКРЫТА
Andy BitOff ( 2004-01-17 01:52 ) [14]
/mrcat © (16.01.04 13:28) [8]
>Andy BitOff © (16.01.04 03:24) [6]
>repne movsb
на 32-х битных не оптимально, гораздо быстрее в купе с repne movsd/
Согласен. Но я ведь привел общий случай. А вопрошающему дорабатывать, я же не буду за него все писать.
В соответствии с соглашениями сбрасывать флаг направления (CLD) не нужно - он сброшен по умолчанию, и после выхода из любой функции/процедуры должен оставаться сброшенным.
Добрый день.
Вопрос заключается в следующем:
Есть указатель на кадр полученный от камеры/файла, но этот кадр отражен зеркально по горизонтали.
Как его максимально быстро перевернуть?
изспользовал такую схему
Копирование/перемещение папки
Спасибо большое Вам за то, что помогаете мне, но у меня ещё один небольшой вопрос: каким образом.
Копирование и перемещение папки с файлами
Существует папка, размещенная по постоянному пути. К примеру "C:\\Programma\directory for.
Копирование и перемещение в Командной строке
Доброго времени суток. Задача - перемещать из сетевой папки(test1) в локальную(test2) все файлы.
видео мерцает, если картинку перерисовывает еще кто-то кроме вас
к обработке это никакого отношения не имеет
Нет. Мерцание происходит в том случае, если обрабатывать непосредственно в отображаемом изображении и в ходе одной обработки менять цвет одних и тех де пикселей или цвета/координаты одних и тех же векторов более одного раза и при этом не блокировать отображение до окончания каждой обработки. Обработка должна или менять каждый цвет/координату ровно один раз, или происходить или строго между кадрами, или во внеэкранном буфере. Тогда мерцать не будет.
согласен.
во времена VGA мы отлавливали прерывания обратного хода луча чтобы сменить картинку в буфере видеокарты
но мерцание мерцанию рознь
иногда тут люди умудряются рисовать на форме, потом форма перерисовывает фон и т.д.
вот там мерцание, так мерцание.
но строго между кадрами в VCL без DirectX невозможно. Так что некоторое мерцание будет присутствовать всегда
. В течении обработки каждый пиксел перекрашивается ровно один раз, мерцания нет. Правда возможны рывки. Но не мерцание. А фокус в том, что здесь сразу вычисляется, будет ли пиксел фоновым, или закрашенным и только потом происходить рисование. А ведь ещё модно рисовать во внеэкранном буфере и выводить, когда буфер завершён. Мерцание происходит от того, что один и тот де пиксел перекрашивается сначала в цвет фона, а потом в цвет изображения, с какой бы частотой это не происходило, это и будет мерцанием. Совсем другое дело, когда по экрану медленно движется объект, фазы его движения перерисовываются часто, а пиксел перекрашивается в цвет фона, когда его через много кадров покинул объект, это уже не мерцание, а само движение.
то что рисование должно происходить во внеэкранном буфере, это, мне кажется, просто очевидно должно быть
← →AllDer ( 2004-01-16 01:01 ) [0]
понял,возник вопрос написать свою
CopyMemoryEx,но даже CopyMemory немогу написать
в Dll system искал - ненашел чтоб dizассемблить.
собственно CopyMemory(Dest,Source:pointer;Length:dword)
источник и приемник и длина.
парился с
procedure ImitationCopy(Start,Finish:poiter;Len:dword);
var
a:dword;
begin
for a:=0 to len do begin
asm
push start
pop a
inc a // +1
push a
pop start
push finish
pop a
inc a // +1
push a
pop finish
end;
Finish:=Start; // присваиваем
<
Но здесь видать по адресу Finish содержимое не меняется,меняется лишь
указатель на ту ячейку и указатель затирается следующим for^ом>
b:^byte;\ byt:byte;\ c:pointer;
c:=Start; // copy pointer
b:=c; // copy в типиз указатель
byt:=b^; // отбираем байт
Finish:=b;//его присваваем
end;
>
Где взять исходник CopyMemory() ?
VMcL ( 2004-01-16 01:20 ) [1]
Посмотри System.Move.
← →AllDer ( 2004-01-16 01:23 ) [2]
А что это System.Move?
есть API func MoveMemory
VMcL ( 2004-01-16 01:36 ) [3]
А есть Delphi"s Move. F1.
← →VMcL ( 2004-01-16 01:38 ) [4]
Насчет исходника CopyMemory: вставь в Delphi-прогу вызов CopyMemory и отладчиком. Но я бы брал всё-таки Move.
← →AllDer ( 2004-01-16 01:42 ) [5]
procedure Move(const Source; var Dest; Count: Integer);
а она с pointer^ми работает?проверю
A: array[1..4] of Char;
B: Integer;
begin
Move(A, B, SizeOf(B)); < SizeOf = safety! >
end;
Andy BitOff ( 2004-01-16 03:24 ) [6]
procedure TForm1.Button1Click(Sender: TObject);
var FromMem,ToMem:Pointer;
Size:Integer;
begin
asm
push edi
push esi
mov esi,[FromMem]
mov edi,[ToMem]
mov ecx,[Size]
repne movsb
pop esi
pop edi
end;
end;
AKul ( 2004-01-16 13:23 ) [7]
> AllDer (16.01.04 01:01)
> for a:=0 to len do begin
> asm
> push start
> pop a
> inc a // +1
> push a
> pop start
>
> push finish
> pop a
> inc a // +1
> push a
> pop finish
> end;
> Finish:=Start; // присваиваем
Не в обиду будет сказано, но что это за бред? Кто тебя на ассемблере учил программировать? Что это за алгоритм такой?
Если перевести это на Delphi, то выглядеть будет приблизительно так:
for a:=0 to len do begin
a:=Start+1; //Зачем здесь ипользовать переменную цикла?
Start:=a;
a:=Finish+1;
Finish:=a;
Алгоритм на Delphi должен быть бризительно следующий:
procedure Copy(var Src,Dest;Count:integer);
Type ArrayType=Array [0..$7FFFFFFE] of byte;
var i:integer;
S,D:^ArrayType;
begin
S:=@Src;D:=@Dest;
for i:=0 to Count do
D^[i]:=S^[i];
end;
При вызове CopyMemory Delphi вызывает не API-функцию с таким именем, а свою, исходный код которой можно найти в Windows.pas:
procedure CopyMemory(Destination: Pointer; Source: Pointer; Length: DWORD);
begin
Move(Source^, Destination^, Length);
end;
Что касается исходного кода API-функции CopyMemory, то он приблизительно такой, как написал Andy BitOff © (16.01.04 03:24) [6] (за исключением того, что следует обнулить флаг направления копирования данных (cld) и он оптимизирован - копируются не байты, а двойные слова).
Еще, CopyMemory (API) используется только не для перекрывающихся диапазонов! Для перекрывающихся диапазонов следует использовать MoveMemory.
← →mrcat ( 2004-01-16 13:28 ) [8]
>Andy BitOff © (16.01.04 03:24) [6]
>repne movsb
на 32-х битных не оптимально, гораздо быстрее в купе с repne movsd
Тимохов ( 2004-01-16 13:53 ) [9]
Хочу сказать, имхо:
Моve быстрее чем api функции. Проверял.
а Move определено в system.pas
Разобраллся . Спасибо
Осталось присабачить,чтоб в чужих процессах
могло пахать.
Тема ЗАКРЫТА
Andy BitOff ( 2004-01-17 01:52 ) [14]
/mrcat © (16.01.04 13:28) [8]
>Andy BitOff © (16.01.04 03:24) [6]
>repne movsb
на 32-х битных не оптимально, гораздо быстрее в купе с repne movsd/
Согласен. Но я ведь привел общий случай. А вопрошающему дорабатывать, я же не буду за него все писать.
В соответствии с соглашениями сбрасывать флаг направления (CLD) не нужно - он сброшен по умолчанию, и после выхода из любой функции/процедуры должен оставаться сброшенным.
Читайте также: