Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 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
2-1166169199
KyRo
2006-12-15 10:53
2007.01.07
Как сделать на компонент полупрозрачным


2-1163146202
inkvizitor
2006-11-10 11:10
2007.01.07
Массив из Мемо


15-1165849993
Rule
2006-12-11 18:13
2007.01.07
Мож кто знает компилятор на windows mobile 5


15-1166392688
Kerk
2006-12-18 00:58
2007.01.07
Google News наконец на русском


15-1166278074
Loginov Dmitry
2006-12-16 17:07
2007.01.07
Matrix32





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский