Форум: "Прочее";
Текущий архив: 2007.01.07;
Скачать: [xml.tar.bz2];
ВнизCompareMem Найти похожие ветки
← →
Rouse_ © (2006-12-13 23:35) [0]Это просто теоретический вопрос.
Надеюсь что все знают, что в 2006-ой Delphi данная функция идет в составе среды под лицензийе MPL в авторстве Александра Шарахова.
http://www.delphimaster.ru/cgi-bin/anketa.pl?id=1084952164
Что меня немного удивило в данной функции, это то, что если третий параметр функции (размер данных, приходит в ЕСХ) ноль, то функция выходет с True.
Теперь вопрос: задача функции является сравнение двух блоков данных, должна ли она возвращать True если данных нет?
← →
Rouse_ © (2006-12-13 23:38) [1]Мы просто сегодня с jack128 по этой теме что-то заспорили...
Его логика - данные равны даже если их размер нулевой.
Моя логика - если размер нулевой, то данных то собственно и нет, поэтому результат должен вернуться False т.к. сравнивать нечего...
← →
Vga © (2006-12-13 23:40) [2]Моя логика - отсутствие данных равно отсутствию данных.
← →
Vga © (2006-12-13 23:41) [3]А вот если раньше в Delphi эта функция была реализована иначе, то правильно будет так, как работала прежняя версия (если я правильно понял)
← →
Gero © (2006-12-13 23:42) [4]> [1] Rouse_ © (13.12.06 23:38)
> Его логика - данные равны даже если их размер нулевой.
А почему нет, между ними ведь нет отличий.
← →
Rouse_ © (2006-12-13 23:43) [5]Раньше True, но ИМХО это не правильно, ведь функция не выполнила сравнения данных...
← →
Kerk © (2006-12-13 23:45) [6]> [5] Rouse_ © (13.12.06 23:43)
s1,s2: string;
s1 := "";
s2 := "";
if s1 = s2 then
...
Тоже самое
← →
Vga © (2006-12-13 23:45) [7]> [5] Rouse_ © (13.12.06 23:43)
Тогда никаких вопросов - правильно, т.к. совместимость.
← →
Rouse_ © (2006-12-13 23:49) [8]Тут как понять, если одним из условий выхода является размер данных, то да, но Compare и особенно Mem выполненно то небыло, почему тогда выход с единицей в ЕАХ?
← →
Юрий Зотов © (2006-12-13 23:50) [9]Функция должна возвращать integer - да, нет, не знаю.
← →
Petr V. Abramov © (2006-12-13 23:52) [10]> ведь функция не выполнила сравнения данных...
и денег ей давать нефиг :)
подойдем по-другому: если данных не было и программа пойдет по true, она будет глючить? в 90% случаев - нет. Если два пустых буфера не равны, будет глючить? :)))
← →
Rouse_ © (2006-12-13 23:53) [11]
> Функция должна возвращать integer - да, нет, не знаю.
Юр, век лампочек прошел :)
Кстати, что также удивило, ни в старой реализации ни в новой нет банального test ecx,ecx после которого можно спокойно выходить. Решение об этом происходит после по факту....
← →
palva © (2006-12-13 23:56) [12]Наверно алгоритм такой. Сначала выходной переменной присваивается True, потом идет цикл: сначала сравниваются первые байты, потом вторые и т. д. Как только байты не совпали, выходной переменной присваивается False и break из цикла. А если цикл вообще не работал, то так и осталось True.
← →
Rouse_ © (2006-12-13 23:56) [13]
> если данных не было и программа пойдет по true, она будет
> глючить?
Дык... я просто был уверен что не нужно утруждаться излишней проверкой на размер и она вернет ложь, оказалось не так. Вынес код к себе в модуль и поправиль, так проще чем кучу проверок ставить :)
← →
Rouse_ © (2006-12-13 23:58) [14]
> palva © (13.12.06 23:56) [12]
В старой было тупо через REPE сделано, у Sha все красивее на несколько порядков, но всеравно, такая мелочь казалось бы ... :)
← →
TUser © (2006-12-14 00:04) [15]зависит от задачи
Есть последовательности двух генов, одна длины ноль и другая - длины ноль. Ясно, чтоэто глюки интернета, базы данных, программы, бухого молекулярного биолога и пр. Данные по определению не равны, т.к. за нулевой длиной скрываются сотни неизвестных букафф.
Есть координаты атомов лиганла. Надо сравнить лиганды в двухз структурах. Если везде длина записи об атомах лиганда - ноль, то значит полное совпадение - нигде лиганда нет.
← →
Rouse_ © (2006-12-14 00:07) [16]Ииии, хорошь ругаца :))
Вопрос в чем, какого спрашивается функция возвращает TRUE если она не произвера сравнение данных (не произвела однозначно, т.к. тест на длинну данных ни там ни ниже нет)function CompareMem(P1, P2: Pointer; Length: Integer): Boolean; assembler;
asm
PUSH ESI
PUSH EDI
MOV ESI,P1
MOV EDI,P2
MOV EDX,ECX
XOR EAX,EAX
AND EDX,3
SAR ECX,2
JS @@1 // Negative Length implies identity.
REPE CMPSD
JNE @@2
MOV ECX,EDX
REPE CMPSB
JNE @@2
@@1: INC EAX
@@2: POP EDI
POP ESI
end;
← →
Sha © (2006-12-14 00:13) [17]Мне кажется, тут логика такая: найдены отличия = false, не найдены = true.
Вроде логично.
Насчет провеки ecx в начале точно не помню.
Но если она не делается, то, значит, потому, что из-за нее тормоза были.
Функция часто используемая, поэтому хотелось сделать,
чтоб все быстрее крутилось...
← →
Rouse_ © (2006-12-14 00:26) [18]
> Sha ©
Спасибо за обьяснение, т.е. упор шел на то что все-же сравниваться будут блоки данных не нулевого размера? Ок, я просто сделал тест ма мультимедийных таймерах... Почти идентично, но с разбросом небольшим, не выяснить дает ли тормоза (ну конечно же дает, но слишком много времени нужно длать чтобы значения разброса стали значительны).
По поводу тормозов
> Kerk © (13.12.06 23:45) [6]
> > [5] Rouse_ © (13.12.06 23:43)
>
> s1,s2: string;
>
> s1 := "";
> s2 := "";
> if s1 = s2 then
> ...
>
> Тоже самое
Пардон, не ответил, это не тоже самое, в данном примере сравниваются два 8-байтных блока памяти, что сам понимаешь никак не сравниться с нулевым размером данных.
← →
Vga © (2006-12-14 00:28) [19]> Пардон, не ответил, это не тоже самое, в данном примере
> сравниваются два 8-байтных блока памяти, что сам понимаешь
> никак не сравниться с нулевым размером данных.
А я где-то читал, что пустая строка - это nil
← →
Rouse_ © (2006-12-14 00:31) [20]
> А я где-то читал, что пустая строка - это nil
Больше такого не читай :)
← →
Petr V. Abramov © (2006-12-14 00:35) [21]> Rouse_ © (13.12.06 23:56) [13]
ай... противоречит принципу полковника Скалозуба :)))
не в части книг, конечно :)))
← →
Sha © (2006-12-14 00:39) [22]> Rouse_ © (14.12.06 00:26) [18]
> упор шел на то что все-же сравниваться будут блоки данных не нулевого размера?
Да. Сравнение пустых блоков, по идее, редкая операция.
Тем не менее, и они сравниваются быстро.
Джон О"Харроу собирал статистику.
Как ни странно, чаще всего программы работают со строками 1 байт :)
И больше половины обращений, кажется, приходится на строки до 16 байт.
Идея состояла не только в написании быстрой функции, но и в обеспечении
максимального быстродействия на коротких блоках.
← →
Rouse_ © (2006-12-14 00:39) [23]Петь, ну не люблю писать нечитабельный код просто,
лишние проверки - глаз теряет мысль при чтении,
сотворил CompareMemEx - генофонд не трогал :)
← →
Sha © (2006-12-14 00:44) [24]> А я где-то читал, что пустая строка - это nil
Так и есть.
Можно, правда, вручную сделать строку нулевой длины, которая не nil, но
это для специльных случаев используется.
← →
Rouse_ © (2006-12-14 00:45) [25]
> Sha ©
Ну мы люди военные, нам более Сунь-Цзы естественнен в плане производительности :)
"Поэтому мудрый полководец должен отнимать провиант у врага. Один бушель зерна противника стоит двадцати наших; одна единица фуража стоит двадцати наших." ;)
← →
Rouse_ © (2006-12-14 00:46) [26]
> Sha © (14.12.06 00:44) [24]
> > А я где-то читал, что пустая строка - это nil
>
> Так и есть.
Строка как бы не есть чистый PChar, бо размер имеет и счетчик ссылок :)
← →
Vga © (2006-12-14 00:49) [27]> [26] Rouse_ © (14.12.06 00:46)
Как я читал, если строка пустая, то память, выделенныя строке, просто освобождается. А переменная соответственно заnilивается.
← →
Rouse_ © (2006-12-14 00:52) [28]Строка в пределах видимости функции как бы существует, раз она видима, значит рефы на нее в примере керка возведены как минимум в единицу. За пределами видимости никто и не спорит.
← →
Petr V. Abramov © (2006-12-14 00:55) [29]> Петь, ну не люблю писать нечитабельный код просто,
а кто любит-то? но, тем не менее, вариант, когда строка пустая - увы, реальный. Поэтому обработать его надо, не завязываясь на результат CompareMem, исключая случаи, когдв ты ТОЧНО ЗНАЕШЬ( и.е. не поленился вспомнить, что про это надо подумать :), что true или false этой ф-ции на пустой строке не приведет к глюку.
Про п-ка Скалозуба: всякие е-нутые ситуации обрабатывать там, где они могут возникнуть, а не где могут иметь последствия. В большинстве случаев обработка будет где-то глубоко в ya.molodetz.system, всегда работать и никого не ...
← →
Sha © (2006-12-14 00:55) [30]Для видимой строки после
s="";
получим
pointer(s)=nil
что легко проверить
← →
Eraser © (2006-12-14 00:58) [31]> [27] Vga © (14.12.06 00:49)
procedure _LStrClr(var S);
{$IFDEF PUREPASCAL}
var
P: PStrRec;
begin
if Pointer(S) <> nil then
begin
P := Pointer(Integer(S) - Sizeof(StrRec));
Pointer(S) := nil;
if P.refCnt > 0 then
if InterlockedDecrement(P.refCnt) = 0 then
FreeMem(P);
end;
end;
{$ELSE}
asm
{ -> EAX pointer to str }
MOV EDX,[EAX] { fetch str }
TEST EDX,EDX { if nil, nothing to do }
JE @@done
MOV dword ptr [EAX],0 { clear str }
MOV ECX,[EDX-skew].StrRec.refCnt { fetch refCnt }
DEC ECX { if < 0: literal str }
JL @@done
LOCK DEC [EDX-skew].StrRec.refCnt { threadsafe dec refCount }
JNE @@done
PUSH EAX
LEA EAX,[EDX-skew].StrRec.refCnt { if refCnt now zero, deallocate}
CALL _FreeMem
POP EAX
@@done:
end;
{$ENDIF}
← →
Rouse_ © (2006-12-14 01:03) [32]Хм, а чтоже еще мы можем получить при Pointer(S1[0]) там же размер лещит нулевой, который при приведении равен NIL?
← →
MikePetrichenko © (2006-12-14 01:04) [33]А вот в WinAPI практически все функции сравнения начинаются с сравнения длины. Если не равна длина, то и данные не равны...
← →
Vga © (2006-12-14 01:04) [34]> [31] Eraser © (14.12.06 00:58)
Да, я уже на это в дебаггрере посмотрел :) Довольно любопытно. Правда, я ошибся с освобождением памяти - она освобождается только если счетчик ссылок равен нулю, а я в [27] сказал не так :(
← →
Sha © (2006-12-14 01:08) [35]Нет.
Pointer(s) всегда возвращает адрес первого символа строки
(или того места, где он мог бы быть в случае пустой строки :)
Это просто приведение типа, можно убедиться в отладчике.
← →
Sha © (2006-12-14 01:09) [36]Последнее к Rouse_ © (14.12.06 01:03) [32] относится
← →
Rouse_ © (2006-12-14 01:13) [37]Саш, мне стыдно такое тебе говорить, но...
if Poiner(S1) = nil then
cmp dword ptr [ebp - $04], $00
← →
Eraser © (2006-12-14 01:13) [38]> [33] MikePetrichenko © (14.12.06 01:04)
дык чтобы определить в PChar длину - нужно найти, где она заканчивается, это не мгновенная операция.
> [32] Rouse_ © (14.12.06 01:03)
дык это ж compiler magic, на самом деле это не начало строки. BDS 2006 вообще не дает к ниму напрямую обращаться.
хотя мож я не совсем уловил, что ты хотел сказать ... )
← →
Sha © (2006-12-14 01:15) [39][ebp - $04] как раз и есть адрес первого символа )
← →
Sha © (2006-12-14 01:16) [40]вернее места, где он лежит
← →
Rouse_ © (2006-12-14 01:25) [41]Sha, понял, но левее 8 байт то всеравно лежит...
← →
Sha © (2006-12-14 01:26) [42]И левее, и правее, но к строке они не имеют никакого отношения...
← →
Германн © (2006-12-14 01:56) [43]
> Rouse_ © (14.12.06 00:07) [16]
>
> Ииии, хорошь ругаца :))
> Вопрос в чем, какого спрашивается функция возвращает TRUE
> если она не произвера сравнение данных (не произвела однозначно,
> т.к. тест на длинну данных ни там ни ниже нет)
>
Сань, хорош баламутить. Как можно однозначно выбрать "да" или "нет" в случае отсутствия данных? ЮЗ предложил наиболее грамотный совет. Использовать три состояния в ответе.
Все прочие рассуждения ориентированы на конкретные задачи. Имхо.
← →
Германн © (2006-12-14 02:24) [44]Я промахнулся :(
Прошу меня извинить.
Ориентировался я на
> Rouse_ © (13.12.06 23:38) [1]
>
> Мы просто сегодня с jack128 по этой теме что-то заспорили.
> ..
> Его логика - данные равны даже если их размер нулевой.
> Моя логика - если размер нулевой, то данных то собственно
> и нет, поэтому результат должен вернуться False т.к. сравнивать
> нечего...
>
← →
Anatoly Podgoretsky © (2006-12-14 09:03) [45]> Rouse_ (14.12.2006 01:25:41) [41]
Поспать не пора?
А то стыдно :-)
На всякий случай маленький ликбез по длинным строкам.
Переменная типа string указывает на первый байт строки, если только строка не пустая, тогда значение указателя равно nil
Если не пустая, то указатель на первый байт строки, а по смещению -4 лежит длина этой строки и по смещению -8 счетчик ссылок, в более старых версиях был еще один член, по смещению -12 было значение зарезервированого количества бай, но в коде не использовалось. То есть указатель это по сути указатель на структуру
RefCount: Integer
Length: Integer
string --> PChar: array [1..Length] of char + #0
При изменении строки, если будет создана копия, то создается новый экземпляр и изменяется переменная string, для того экземпляра, который создается, у остальных экземляров уменьшается счетчик и если он равен нулю, то память освобождается, а переменным присваивается nil
← →
Anatoly Podgoretsky © (2006-12-14 09:03) [46]Удалено модератором
← →
Anatoly Podgoretsky © (2006-12-14 09:09) [47]> Anatoly Podgoretsky (14.12.2006 09:03:45) [45]
Для совместимости с WinAPi - если передается строка через приведение к PChar, то в при пустой строке передается указатель на внутренний буфер array[0..0] of char, который содержит только символ #0 и что очень важно, данная память Read Only, на этом многие прокалываются, когда передают указатель в WinAPI
Пример неправильной работы
S := "";
CharToOem(PChar(S), PChar(S));
А вот пример правильной работы
S := "";
if S <> "" then CharToOem(PChar(S), PChar(S));
← →
pasha_golub © (2006-12-14 10:19) [48]
> Anatoly Podgoretsky © (14.12.06 09:03) [46]
>
> Удалено модератором
Сам пью, сам гуляю? :))
← →
Sha © (2006-12-14 11:01) [49]> Anatoly Podgoretsky © (14.12.06 09:09) [47]
> А вот пример правильной работы
> S := "";
> if S <> "" then CharToOem(PChar(S), PChar(S));
Это был хитрый пример не всегда правильной работы :)
Можете проверить на этом коде:
s:="123";
if s<>"" then CharToOem(PChar(S), PChar(S));
А вот как надо :)
s:="123";
UniqueString(s);
if s<>"" then CharToOem(pointer(S), pointer(S));
← →
Vga © (2006-12-14 13:23) [50]> [49] Sha © (14.12.06 11:01)
> UniqueString(s);
А что эта функция делает? Создает копию строки?
← →
jack128 © (2006-12-14 13:46) [51]Vga © (14.12.06 13:23) [50]
да. Создает реальную копию, а не просто увеличивает счетчик ссылок..
← →
Sha © (2006-12-14 13:49) [52]Создает копию неуникальной строки.
Если строка уникальна (счетчик ссылок равен 1), то она ничего не делает.
← →
Sha © (2006-12-14 13:52) [53]Ну и, разумеется, пустая строка при этом не расщепляется, т.к. расщеплять нечего.
Т.е. все пустые строки считаются уникальными.
← →
Anatoly Podgoretsky © (2006-12-14 14:00) [54]> pasha_golub (14.12.2006 10:19:48) [48]
А что, разве неприкасаемый?
Это бул дубль
← →
Anatoly Podgoretsky © (2006-12-14 14:02) [55]> Sha (14.12.2006 11:01:49) [49]
Не спорю, я вообще то говорил об другом варианте, когда строка не константа, а например считывается с файла, но это тоже пример неправильной работе, при том же при по той же самой причине - константная строка.
← →
Юрий Зотов © (2006-12-14 15:54) [56]> Rouse_ © (13.12.06 23:53) [11]
Саш, как видишь, даже такая простая и чисто компьютерная задача - и то уже не укладывается в рамки "ать-два" (т.е., "ноль-единица"). Что уж тогда говорить о задачах, вытекающих из жизни?
"Век лампочек" не пройдет никогда, Саш. Потому что он вовсе не век.
:о)
← →
Eraser © (2006-12-14 20:15) [57]кстати по-поводу сабжа, winAPI возвращает true, даже если строки пустые, но при этом указывает соответствующую ошибку, которую можно получить через getlasterror.
← →
Mystic © (2006-12-14 21:05) [58]Определение:
Два блока памяти равны, (а) у них совпадает длина N(б) если не существует такого номера i, (0 <= i <= N), что i-й байт первого блока отличается от i-го байта второго блока.
Определения такого рода общеприняты в математике (один пустой граф изоморфен другому пустому графу, и т. д.) Впрочем это достаточно оцевидно, иначе в большиство математических результатов надо было вносить оговорки.
Из этого определения видно, что два пустых блока равны между собой. Более того, при таком определении равенства блоков, функция CompareMem является отношением эквивалентности, что является полезным свойством.
← →
default © (2006-12-14 21:48) [59]давайте ещё поспорьте правильно-ли, что любое число в нулевой степени это 1, что факториал нуля единица, ...
такие вопросы решаются или в пользу удобства, или в пользу того, что более очевидно, в пользу...
Страницы: 1 2 вся ветка
Форум: "Прочее";
Текущий архив: 2007.01.07;
Скачать: [xml.tar.bz2];
Память: 0.61 MB
Время: 0.012 c