Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Прочее";
Текущий архив: 2016.01.03;
Скачать: [xml.tar.bz2];

Вниз

Никто не хочет задачку от GunSmoker-а решить? :)   Найти похожие ветки 

 
Rouse_ ©   (2015-04-29 21:56) [0]

Сама задача: http://www.gunsmoker.ru/2015/04/task-18.html
Если чесно я не смог, и сделал обоснование почему не смог:
http://alexander-bagel.blogspot.ru/2015/04/18-gunsmoker.html


 
Дмитрий С ©   (2015-04-29 22:10) [1]

Код в задаче и у тебя разный.


 
Kilkennycat ©   (2015-04-29 22:12) [2]

if AWnd = Wnd then после си я такое видеть спокойно не могу...


 
Дмитрий С ©   (2015-04-29 22:21) [3]

Мне кажется дело вот в чем:
Передаем мы значение LPARAM(Wnd)
А ожидаем указатель на значение  const AParam: LPARAM


 
Rouse_ ©   (2015-04-29 22:59) [4]


> Дмитрий С ©   (29.04.15 22:10) [1]
> Код в задаче и у тебя разный.

Как это?
Первая часть обзора была по первому вопросу: http://www.gunsmoker.ru/2015/04/task-18-1.html
Вторая, по второму: http://www.gunsmoker.ru/2015/04/task-18.html

Собственно первый не интересен, ситуемина именно со вторым :)


 
Eraser ©   (2015-04-29 23:00) [5]

Не совсем понятно, в чем суть задачи.

Это я прочитал от предыдущего вопроса.

>> Не обращайте внимание на его бессмысленность, вопрос не в этом, а в корректности кода.

Но код то вполне рабочий, по крайней мере у меня.


 
Rouse_ ©   (2015-04-29 23:00) [6]


> Передаем мы значение LPARAM(Wnd)
> А ожидаем указатель на значение  const AParam: LPARAM

Это как так? Что передали на EnumWindows то и получили в LPARAM без указателей а как есть.


 
Rouse_ ©   (2015-04-29 23:01) [7]


> Eraser ©   (29.04.15 23:00) [5]
> Не совсем понятно, в чем суть задачи.

В том что в данном коде есть ошибка.


 
Кто б сомневался ©   (2015-04-29 23:21) [8]

Вариант A с багом, почему Rouse рассказал, даже на него попадал,  

Поэтому так делаю:


var
 vData: TDataRec;

 function EnumWindowsProc(aWindow: HWND; aData: LPARAM): Bool; stdcall;
 ..

EnumWindows(@EnumWindowsProc, LPARAM(@vData));

Вариант отработан годами.

в варианте B вроде нет проблем, кроме того что меня const смущают, но разбираться влом :) .


 
Eraser ©   (2015-04-29 23:33) [9]

да вариант A вообще дырявый, чего только стоит обращение к Caption, а вот со вторым засада )


 
Rouse_ ©   (2015-04-29 23:37) [10]

Второй меня вообще убил - ну нет там блин ошибки :)))


 
Rouse_ ©   (2015-04-29 23:41) [11]


> кроме того что меня const смущают, но разбираться влом :
> ) .

const перепроверял - асм выхлоп идентичен.


 
Rouse_ ©   (2015-04-29 23:43) [12]

Да и тем более параметры идут не BYREF, а const - сугубо дельфийский момент работающий  как директива.


 
Eraser ©   (2015-04-29 23:52) [13]

В варианте А у меня ошибку гарантированно дает вот такой код (причем 64 битная версия сыпется с AV)

procedure TForm1.Button2Click(Sender: TObject);

 function EnumWindowsProc(const AWnd: HWND; const AParam: LPARAM): BOOL; stdcall;
 begin

   Caption := "OK";
   Result := True;
 end;

begin

 EnumWindows(@EnumWindowsProc, 0);
end;


возможно, что-то связанное с этим и в варианте Б.


> Кто б сомневался ©   (29.04.15 23:21) [8]

procedure TForm1.Button2Click(Sender: TObject);
var
 //Wnd: HWND;
 vData: Integer;

 function EnumWindowsProc(const AWnd: HWND; const AParam: LPARAM): BOOL; stdcall;
 begin

   Caption := "OK";
   Result := True;
 end;

begin
 //Wnd := Handle;
 EnumWindows(@EnumWindowsProc, LPARAM(@vData));
 //EnumWindows(@EnumWindowsProc, 0);
end;


аналогично.


 
Кто б сомневался ©   (2015-04-29 23:56) [14]


> Eraser ©   (29.04.15 23:33) [9]
>
> да вариант A вообще дырявый, чего только стоит обращение
> к Caption



> Eraser ©   (29.04.15 23:52) [13]
> В варианте А у меня ошибку гарантированно дает вот такой
> код
function EnumWindowsProc(const AWnd: HWND; const AParam: LPARAM): BOOL; stdcall;
 begin

   Caption := "OK";



Вас там двое чтоле?


 
Rouse_ ©   (2015-04-30 00:02) [15]


> Eraser ©   (29.04.15 23:52) [13]
> В варианте А у меня ошибку гарантированно дает вот такой
> код

Так ясен пень, тыж мое обоснование сначала прочти.
http://alexander-bagel.blogspot.ru/2015/04/18-gunsmoker.html
Кому ты Caption меняешь, если Self не доступен?


 
Кто б сомневался ©   (2015-04-30 00:03) [16]

Второму Eraser: в EnumWindowsProc нельзя обращаться к любым переменным, которые находятся вне EnumWindowsProc = AV. Только перекидывать адрес через LPARAM.


 
Rouse_ ©   (2015-04-30 00:04) [17]

Народ вон уже сделал первое предположение что CONST в 64 битах может повести себя не так как задумано:
http://www.gunsmoker.ru/2015/04/task-18.html
Завтра буду проверять.


 
Eraser ©   (2015-04-30 00:08) [18]


> Кто б сомневался ©   (30.04.15 00:03) [16]

я это понимаю, там другой менеджер памяти. просто в том исследовании, что провел Rouse_, на сколько я понял, выявлены ошибки, помимо этой.


 
Германн ©   (2015-04-30 00:56) [19]


> Никто не хочет задачку от GunSmoker-а решить? :)
>
> Rouse_ ©   (29.04.15 21:56)  

Комментарий от АА в твоём блоге просто убил.


 
Дмитрий С ©   (2015-04-30 03:42) [20]


> Это как так? Что передали на EnumWindows то и получили в
> LPARAM без указателей а как есть.

Разве const не превращает параметр в переданный по ссылке? Тем самым неявно ожидая указатель вместо значения.


 
brother ©   (2015-04-30 08:00) [21]

ну яб еще
Result := False;
в начале функции поставил, но это так... для явного так сказать


 
Дмитрий С ©   (2015-04-30 10:08) [22]


> Rouse_ ©   (30.04.15 00:04) [17]



{$APPTYPE CONSOLE}
procedure TForm1.Button1Click(Sender: TObject);
function EnumWindowsProc(const AWnd: HWND; const AParam: LPARAM): BOOL; stdcall;
 var
   Wnd: HWND;
 begin
   Wnd := HWND(AParam);
   Writeln("C ", Wnd);
   if AWnd = Wnd then
     Result := True
   else
     Result := False;
 end;

var
 Wnd: HWND;
begin
 Wnd := Handle;
 Writeln("A ", Wnd);
 EnumWindows(@EnumWindowsProc, LPARAM(Wnd));
 Writeln("B ", Wnd);
end;

Под 32 бита:
A 14681046
C 14681046
B 14681046

Под 64 бита:
A 11668374
C 65535
B 11668374

Под 64 бита без const:
A 19536768
C 65535
B 19536768

Так что явно что-то не так.

Вот асм:

Unit1.pas.31: begin
000000000069BBD0 55               push rbp
000000000069BBD1 4883EC30         sub rsp,$30
000000000069BBD5 488BEC           mov rbp,rsp
000000000069BBD8 48894D40         mov [rbp+$40],rcx
000000000069BBDC 48895548         mov [rbp+$48],rdx
000000000069BBE0 4C894550         mov [rbp+$50],r8
Unit1.pas.32: Wnd := HWND(AParam);
000000000069BBE4 488B4550         mov rax,[rbp+$50]
000000000069BBE8 48894520         mov [rbp+$20],rax
Unit1.pas.33: Writeln("C ", Wnd);
000000000069BBEC 488B0DBD6C0400   mov rcx,[rel $00046cbd]
000000000069BBF3 488D154E000000   lea rdx,[rel $0000004e]
000000000069BBFA E8C1F1D6FF       call @Write0UString
000000000069BBFF 4889C1           mov rcx,rax
000000000069BC02 488B5520         mov rdx,[rbp+$20]
000000000069BC06 E8355AD7FF       call @Write0UInt64
000000000069BC0B 4889C1           mov rcx,rax
000000000069BC0E E81DF3D6FF       call @WriteLn
000000000069BC13 E898CFD6FF       call @_IOTest
Unit1.pas.34: if AWnd = Wnd then
000000000069BC18 488B4548         mov rax,[rbp+$48]
000000000069BC1C 483B4520         cmp rax,[rbp+$20]
000000000069BC20 7509             jnz EnumWindowsProc + $5B
Unit1.pas.35: Result := True
000000000069BC22 C7452CFFFFFFFF   mov [rbp+$2c],$ffffffff
000000000069BC29 EB07             jmp EnumWindowsProc + $62
Unit1.pas.37: Result := False;
000000000069BC2B C7452C00000000   mov [rbp+$2c],$00000000
Unit1.pas.38: end;
000000000069BC32 8B452C           mov eax,[rbp+$2c]
000000000069BC35 488D6530         lea rsp,[rbp+$30]
000000000069BC39 5D               pop rbp
000000000069BC3A C3               ret
000000000069BC3B 00B0040200FF     add [rax-$00fffdfc],dh
000000000069BC41 FFFF             db $ff $ff
000000000069BC43 FF02             inc dword ptr [rdx]
000000000069BC45 0000             add [rax],al
000000000069BC47 004300           add [rbx+$00],al
000000000069BC4A 2000             and [rax],al
000000000069BC4C 0000             add [rax],al
000000000069BC4E CC               int 3
000000000069BC4F CC               int 3
Unit1.pas.42: begin
000000000069BC50 55               push rbp
000000000069BC51 4883EC30         sub rsp,$30
000000000069BC55 488BEC           mov rbp,rsp
000000000069BC58 48894D40         mov [rbp+$40],rcx
000000000069BC5C 48895548         mov [rbp+$48],rdx
Unit1.pas.43: Wnd := Handle;
000000000069BC60 488B4D40         mov rcx,[rbp+$40]
000000000069BC64 E82735F2FF       call TWinControl.GetHandle
000000000069BC69 48894528         mov [rbp+$28],rax
Unit1.pas.44: Writeln("A ", Wnd);
000000000069BC6D 488B0D3C6C0400   mov rcx,[rel $00046c3c]
000000000069BC74 488D156D000000   lea rdx,[rel $0000006d]
000000000069BC7B E840F1D6FF       call @Write0UString
000000000069BC80 4889C1           mov rcx,rax
000000000069BC83 488B5528         mov rdx,[rbp+$28]
000000000069BC87 E8B459D7FF       call @Write0UInt64
000000000069BC8C 4889C1           mov rcx,rax
000000000069BC8F E89CF2D6FF       call @WriteLn
000000000069BC94 E817CFD6FF       call @_IOTest
Unit1.pas.45: EnumWindows(@EnumWindowsProc, LPARAM(Wnd));
000000000069BC99 488D0D30FFFFFF   lea rcx,[rel $ffffff30]
000000000069BCA0 488B5528         mov rdx,[rbp+$28]
000000000069BCA4 E84701D8FF       call EnumWindows
Unit1.pas.46: Writeln("B ", Wnd);
000000000069BCA9 488B0D006C0400   mov rcx,[rel $00046c00]
000000000069BCB0 488D1545000000   lea rdx,[rel $00000045]
000000000069BCB7 E804F1D6FF       call @Write0UString
000000000069BCBC 4889C1           mov rcx,rax
000000000069BCBF 488B5528         mov rdx,[rbp+$28]
000000000069BCC3 E87859D7FF       call @Write0UInt64
000000000069BCC8 4889C1           mov rcx,rax
000000000069BCCB E860F2D6FF       call @WriteLn
000000000069BCD0 E8DBCED6FF       call @_IOTest
Unit1.pas.47: end;
000000000069BCD5 488D6530         lea rsp,[rbp+$30]
000000000069BCD9 5D               pop rbp
000000000069BCDA C3               ret


 
Дмитрий С ©   (2015-04-30 10:26) [23]

Если вынести вложенную функцию - то работает как надо. Да и в документации явно написано:
Nested procedures and functions (routines declared within other routines) cannot be used as procedural values, nor can predefined procedures and functions.

http://docwiki.embarcadero.com/RADStudio/XE8/en/Procedural_Types#Method_Pointers


 
Rouse_ ©   (2015-04-30 11:02) [24]


> Дмитрий С ©   (30.04.15 10:08) [22]

Ага, я тоже этот момент проверил и уже в статейке обновил :)
Вот только причину такого поведения не стал искать :)


 
Rouse_ ©   (2015-04-30 11:06) [25]

Ещеб понять что это за пресловутое значение в R8 передается, ну да шут с ним, главное ошибка прояснилась :)


 
Дмитрий С ©   (2015-04-30 12:28) [26]

Кстати я с тобой не согласен на счет того что плохо, что компилятор дает компилировать такое. Я думаю что плохо то, что это работает не так как ожидается.


 
Rouse_ ©   (2015-04-30 13:09) [27]

Спорный момент.


 
Юрий Зотов ©   (2015-04-30 13:40) [28]

Я на эту ошибку напоролся лет 15 назад, когда еще не было ни 64 бит, ни описателя const в параметрах. Все оказалось просто: вынес вложенный  callback наружу - и заработало.


 
Rouse_ ©   (2015-04-30 17:16) [29]

ЗЫ: обновил обзорку, раскрыл тему относящуюся к вопросу:

> Дмитрий С ©   (30.04.15 12:28) [26]


Добавил описание причин такого поведения по второй части.
http://alexander-bagel.blogspot.ru/2015/04/18-gunsmoker.html

Почти статья получилась :)))


 
Palladin ©   (2015-04-30 17:28) [30]


> Я на эту ошибку напоролся лет 15 назад,

+1


 
Palladin ©   (2015-04-30 17:30) [31]

вообще хотелось бы сказать, что вложенная в процедуру процедура является процедурой, вложенная процедура в метод, является методом


 
Rouse_ ©   (2015-04-30 21:39) [32]

Сашка крут, и специально под меня, после моего анализа выложил третий вариант проблемы :)
http://www.gunsmoker.ru/2015/04/task-18-3.html
Жалко что данная задача легко решилась (небольшая девиация), но, впрочем, вот вам задачка на выходные (кому не лень).
ЗЫ: сразу скажу там не все так просто как кажется, с учетом моего предыдущего анализа кода :)


 
Юрий Зотов ©   (2015-04-30 22:15) [33]

Даже без анализа - коллбэк должен возвращать BOOL, а не Boolean.


 
Rouse_ ©   (2015-04-30 22:28) [34]


> Юрий Зотов ©   (30.04.15 22:15) [33]

Допустим, но зачем, если учитывать что данные на стеке 4 байтовые (после любого PUSH) да и EAX регистр 32 бита? :)


 
Rouse_ ©   (2015-04-30 22:36) [35]

Блин - пардоньте, именно этот цимус я тебе и рассказывал.
Юрч не давай пока ответ плз.


 
Дмитрий С ©   (2015-05-01 13:55) [36]


> да и EAX регистр 32 бита? :)


Unit1.pas.35: if AWnd <> Wnd then
005B46CC 8B4508           mov eax,[ebp+$08]
005B46CF 3B45F8           cmp eax,[ebp-$08]
005B46D2 7406             jz $005b46da
Unit1.pas.36: Result := True
005B46D4 C645FF01         mov byte ptr [ebp-$01],$01
005B46D8 EB04             jmp $005b46de
Unit1.pas.38: Result := False;
005B46DA C645FF00         mov byte ptr [ebp-$01],$00
Unit1.pas.39: end;
005B46DE 8A45FF           mov al,[ebp-$01]

В остальной части EAX будут остатки от хендлов.


 
Rouse_ ©   (2015-05-01 14:00) [37]

cравнение идет test eax, eax
суть не в этом


 
Rouse_ ©   (2015-05-01 14:04) [38]

ну либо в 64 битах
xor ebx,ebx
call r15
cmp eax,ebx
jz


 
Дмитрий С ©   (2015-05-01 14:06) [39]


> суть не в этом

В этом.
Вот пример наглядно демонстрирующий:


function EnumWindowsProc(const AWnd: HWND; const AParam: LPARAM): Boolean; stdcall;
var
 Wnd: HWND;
begin
 Wnd := HWND(AParam);
 if AWnd = Wnd then
   Result := True
 else
   Result := False;
end;

procedure TForm1.Button1Click(Sender: TObject);
type
 TEnumWindowsProc = function (const AWnd: HWND; const AParam: LPARAM): Bool; stdcall;
var
 Proc: TEnumWindowsProc;
begin
 Proc := @EnumWindowsProc;
 ShowMessage(BoolToStr(Proc(23456789, 98765432), True)); // Показывает True, а должен False
end;


 
Rouse_ ©   (2015-05-01 14:09) [40]

Показывает False, ты уверен что пример правильный?



Страницы: 1 2 вся ветка

Форум: "Прочее";
Текущий архив: 2016.01.03;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.56 MB
Время: 0.002 c
2-1403935862
cr@nk
2014-06-28 10:11
2016.01.03
on E: Exception do в DataModule и консольное приложение


15-1430999628
фыва
2015-05-07 14:53
2016.01.03
Годную книжку по C#


2-1403942704
Sakipiel
2014-06-28 12:05
2016.01.03
Pascal Script передать указатель на контрол


15-1430333783
Rouse_
2015-04-29 21:56
2016.01.03
Никто не хочет задачку от GunSmoker-а решить? :)


15-1430907464
кгшзх
2015-05-06 13:17
2016.01.03
пока строчил - закрыли (сниффер)





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский