Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.11.12;
Скачать: CL | DM;

Вниз

AV при выполнении метода TObjectList.Sort   Найти похожие ветки 

 
Rule ©   (2006-10-25 13:36) [0]

не пойму почему выходит AV, сам AV происходит в процедуре сортировки, значит вызываю процедуру таким образом   Columns.Sort(dmCommon.MethodAddress("ComparePosColumnsObjects"));
сама прцедруа сортировки такова
function TdmCommon.ComparePosColumnsObjects(Item1,
 Item2: Pointer): Integer;
begin
 Result := TEntityColumn(Item1).Pos-TEntityColumn(Item2).Pos
end;
трассировка показала, что TEntityColumn(Item1).Pos - нормальный, а TEntityColumn(Item2).Pos - недоступное значение ...
я думал что в списке есть указатели на несуществующие объекты, но перед вызовом сортировки непосредственно (перед Columns.Sort(dmCommon.MethodAddress("ComparePosColumnsObjects"));) я написал вот такой код
 for i:= 0  to Columns.Count-1 do Dialogs.ShowMessage(IntToStr(TEntityColumn(Columns[i]).Pos));
и он отработал нормально, значит несуществующих объектов у меня нет ....
подскажите куда ещё можно копать
ЗЫ: код работал нормально вроде, хотя у меня уже сомнения по этому поводу ... но в этой части кода я не ковырял вообще ....
спасибо всем за внимание ...


 
Джо ©   (2006-10-25 13:39) [1]

Не знаю (и не указано), что такое есть Columns, но — TObjectList.Sort"у нужно передавать адрес регулярной процедуры, а не метода.


 
Сергей М. ©   (2006-10-25 13:40) [2]

Параметром метода TList.Sort д.б. адрес регулярной функции, а не адрес функционального метода.


 
Джо ©   (2006-10-25 13:40) [3]

Ну, и, соответственно, неявный параметр Self портит всю малину остальным, следующим за ним, параметрам :)


 
Сергей М. ©   (2006-10-25 13:41) [4]

Т.е. погнали в "Начинающие"


 
Rule ©   (2006-10-25 13:46) [5]

Джо ©   (25.10.06 13:40) [3]
где Self ????


 
Джо ©   (2006-10-25 13:47) [6]

> [5] Rule ©   (25.10.06 13:46)
> Джо ©   (25.10.06 13:40) [3]
> где Self ????

Это неявный параметр, который передается в методы объектов.


 
Rule ©   (2006-10-25 13:48) [7]

Сергей М. ©   (25.10.06 13:40) [2]
Джо ©   (25.10.06 13:39) [1]
а в чем разница между регулярной функцией в данном случае и функциональным методом ??????
вот код примера из справки делфи
function CompareNames(Item1, Item2: Pointer): Integer;
begin
 Result := CompareText((Item1 as TComponent).Name, (Item2 as TComponent).Name);
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
 List1.Sort(@CompareText);
end;
передается адрес функции, какя разница если я передам адресс метода ????


 
Джо ©   (2006-10-25 13:49) [8]

Метод:
TObj = class
 procedure X (A,B: Integer);
end;
При его вызове, фактически будет помещено в стек: Self,A,B.

Регулярная процедура:
procedure X (A,B: Integer);
При ее вызове в стек будет помещено A,B.

Но это детали. А главное: [1],[2].


 
Rule ©   (2006-10-25 13:49) [9]

Джо ©   (25.10.06 13:47) [6]
это я то понимаю :-)))) но как он портит картину, функция возвращает просто число, в вычислении оно тут не учавствует, или ты имеешь ввиду что там в списке параметров присутствует Селф, который невидно и он портит всю малину ???


 
Сергей М. ©   (2006-10-25 13:49) [10]


> Rule ©   (25.10.06 13:48) [7]



> в чем разница


Сейчас будет портация в "Начинающие".


 
Rule ©   (2006-10-25 13:51) [11]

Джо ©   (25.10.06 13:49) [8]
Метод:
TObj = class
procedure X (A,B: Integer);
end;
При его вызове, фактически будет помещено в стек: Self,A,B.

помоему в стек ложится так Self,B,A  а обратно берется в обратном порядке тоесть A,B,Self, что ни в коем случае не должно мешать ...


 
Rule ©   (2006-10-25 13:51) [12]

Сергей М. ©   (25.10.06 13:49) [10]
я не имел ввиду разница в определении, я имел в виду раница в данном случае ...


 
Rule ©   (2006-10-25 13:51) [13]

тем более это все работало до опредленнного момента


 
Джо ©   (2006-10-25 13:52) [14]

В итоге, когда ты такое проделываешь, то в Sort попадает:
Вместо A -> Self (неверный)
Вместо B -> A
И еще лишний параметр B, отсюда, видимо, и AV при нарушении стека.


 
Rule ©   (2006-10-25 13:53) [15]

так чтото я перерабтался ... помоему начинаю въезжать где я промазнулся ...


 
Rule ©   (2006-10-25 13:54) [16]

тогда интересует вопрос как оно могло раньше все работать ... я то был уверен что ему не обязательно регулярная функция нужна была ...


 
Rule ©   (2006-10-25 14:00) [17]

огромное всем спасибо :-) получилось вроде, ща потестю нормально ... перечитал хэлп, про то что это должна быть регулярная функция ничего не сказано ...


 
pasha_golub ©   (2006-10-25 14:00) [18]


> Сергей М. ©   (25.10.06 13:49) [10]

Не такой уж и простой вопрос, чтобы в Начинающих его.


 
Джо ©   (2006-10-25 14:01) [19]

Не, с порядком я напутал. Передаваться будет так:
Вместо A -> B
Вместо B -> Self (нулевой).
Вместо Self -> Вообще хрен знает что.

Вроде так. Жаль, сейчас нет времени поразмыслить, убегаю...


 
Джо ©   (2006-10-25 14:02) [20]

> перечитал хэлп, про то что это должна быть регулярная функция
> ничего не сказано ...

Дык смотри определение:
procedure Sort(Compare: TListSortCompare);
type
TListSortCompare = function (Item1, Item2: Pointer): Integer; // of object не указано.


 
Rule ©   (2006-10-25 14:06) [21]

Джо ©   (25.10.06 14:02) [20]
а ну да в принципе ...


 
Palladin ©   (2006-10-25 14:12) [22]

не в принципе, а реально


 
Сергей М. ©   (2006-10-25 14:17) [23]


> Rule


какой нафиг "стек" ?

соглашение - дифолтное

Первые три параметра - в РОН, остальные - в стек.

TListSortCompare - рег.ф-ция, с двумя параметрами.

Item1 ожидается в EAX, Item2  - в EDX.

Если же ты подставишь адрес не рег.ф-ции, а функц.метода класса, то этот функц.метод класса будет ожидать в EAX не Item1, а self .. дальше и объяснять не надо, дальше - бардак


 
Rule ©   (2006-10-25 14:57) [24]

Сергей М. ©   (25.10.06 14:17) [23]
спасибо за подробные разьяснения, буду впредь внимательней ...


 
MetalFan ©   (2006-10-25 15:43) [25]

попалась интересная функция:
function MethodToProcedure(self: TObject; methodAddr: pointer) : pointer;
type
 TMethodToProc = packed record
   popEax   : byte;                  // $58      pop EAX
   pushSelf : record                 //          push self
                opcode  : byte;      // $B8
                self    : pointer;   // self
              end;
   pushEax  : byte;                  // $50      push EAX
   jump     : record                 //          jmp [target]
                opcode  : byte;      // $FF
                modRm   : byte;      // $25
                pTarget : ^pointer;  // @target
                target  : pointer;   //          @MethodAddr
              end;
 end;
var mtp : ^TMethodToProc absolute result;
begin
 mtp := VirtualAlloc(nil, sizeOf(mtp^), MEM_COMMIT, PAGE_EXECUTE_READWRITE);
 with mtp^ do begin
   popEax          := $58;
   pushSelf.opcode := $68;
   pushSelf.self   := self;
   pushEax         := $50;
   jump.opcode     := $FF;
   jump.modRm      := $25;
   jump.pTarget    := @jump.target;
   jump.target     := methodAddr;
 end;
end;

кто чего скажет? может кто протестит?


 
Ketmar ©   (2006-10-25 15:48) [26]

>[25] MetalFan(c) 25-Oct-2006, 15:43
>кто чего скажет? может кто протестит?
может, сам и протестишь? %-)


 
Rule ©   (2006-10-25 19:33) [27]

а щас проверим ...


 
Ketmar ©   (2006-10-25 20:08) [28]

а что тут тестить? и так видно, что бредятина.


 
default ©   (2006-10-25 20:19) [29]

ещё и обход дельфийского менеджера памяти:)
не код, а ужас
пример того, что лишние знания иногда вредят:)
в данном случае - знание ассемблера:)


 
Ketmar ©   (2006-10-25 20:37) [30]

>[29] default(c) 25-Oct-2006, 20:19
>пример того, что лишние знания иногда вредят:)
знания -- вряд ли. что-то я у того, кто это написал, знаний не замечаю. только умение находить себе проблемы на анус.

2MetalFan: не ройся больше в помойках. там ещё и не такой мусор можно найти. %-)


 
default ©   (2006-10-25 20:53) [31]

Ketmar ©   (25.10.06 20:37) [30]
это да
ну если бы он вообще не знал о ассеблере, то такая бы бредятина не увидела бы свет


 
Ketmar ©   (2006-10-25 21:07) [32]

>[31] default(c) 25-Oct-2006, 20:53
лучше бы он не знал об интернете.


 
MetalFan_pda   (2006-10-25 23:44) [33]

приведеннный код сперт из библиотеки mad... (madTools.pas) работоспособность не проверял


 
default ©   (2006-10-26 00:08) [34]

кстати вроде как у всех рекордов надо packed ставить, а не у внешнего чтобы всё шло строго друг за другом


 
Ketmar ©   (2006-10-26 01:26) [35]

>[33] MetalFan_pda 25-Oct-2006, 23:44
>приведеннный код сперт из библиотеки mad... (madTools.pas)
я считал автора mad"а вменяемым. или ты привёл обломок, который сам по себе "не играет", или даже не знаю, что...


 
MetalFan ©   (2006-10-26 08:58) [36]

выдержка из хелпа madCollection

Sometimes you need to give a procedure address in to a Windows API, but you would rather give in a method instead. In such a situation the function "MethodToProcedure" can come in handy. You give in a method address and your current "Self" value and you get a procedure address as the result, which you then can give in to a Windows API.

Please note that this works only for *stdcall* methods! Don"t use it for any other calling convention! (But since almost all Windows APIs are stdcall, this should not be a big problem.)

After you don"t need the procedure pointer anymore, please free it with "VirtualFree".
function MethodToProcedure (self       : TObject;
                           methodAddr : pointer) : pointer; overload;

function MethodToProcedure (method     : TMethod) : pointer; overload;

Here comes a little example which demonstrates a correct and useful usage of "MethodToProcedure":
unit EnumWindows;

// this unit implements a little class named TEnumWindows, which does nothing
// but enumerate all windows

interface

implementation

uses Windows, SysUtils, madTools;

type
 TEnumWindows = class
 private
   function EnumCallbackMethod(window: dword; lParam: integer) : bool; stdcall;
 public
   constructor Create;
 end;

constructor TEnumWindows.Create;
var EnumCallbackProc : pointer;
begin
 inherited;

 // you must give in a procedure address into EnumWindows
 // if you would give in "@TWindowList.EnumCallbackMethod" your code would crash
 // because methods have an additional hidden "Self" parameter
 // so we need to convert our method to a procedure first
 EnumCallbackProc := MethodToProcedure(Self, @TEnumWindows.EnumCallbackMethod);

 // "EnumCallbackProc" now contains a pointer to a newly allocated procedure
 // which does nothing but jump to our "EnumCallbackMethod" with the correct parameters
 EnumWindows(EnumCallbackProc, 0);

 // don"t forget to free the allocated procedure
 VirtualFree(EnumCallbackProc, 0, MEM_RELEASE);
end;

function TEnumWindows.EnumCallbackMethod(window: dword; lParam: integer) : bool; stdcall;
begin
 result := true;

 // do anything with the "window"s you get here...
 [...]
end;

end.


 
MetalFan ©   (2006-10-26 10:05) [37]

что скажете? по прежнему бред? объясните, почему это не будет работать?
плз, в асме не силен, но интересно!


 
icWasya ©   (2006-10-26 11:29) [38]

>Rule ©   (25.10.06 13:51) [13]
>тем более это все работало до опредленнного момента

поскольку параметры передаются через регистры, то может оказаться, что в регистрах случайно могут оказаться правильные значения :)


 
Сергей М. ©   (2006-10-26 12:43) [39]


> MetalFan ©   (25.10.06 15:43) [25]
> попалась интересная функция:


Ее и искать не нужно было, она всегда под рукой - Make/FreeObjectInstance().
По ее образу и подобию до смешного легко и просто сотворить MakeCompareRegularFuncFromCompareMethod().


 
Ketmar ©   (2006-10-26 14:01) [40]

>[36] MetalFan(c) 26-Oct-2006, 08:58
>выдержка из хелпа madCollection
молодец. с этого и надо было начинать смотрим внимательно:

>Sometimes you need to give a procedure address in to a
>Windows API
...
>Please note that this works only for *stdcall* methods!
вот теперь всё становится на свои места. а то ты уж меня перепугал совсем -- я думал, madshi свихнулся... %-)



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

Текущий архив: 2006.11.12;
Скачать: CL | DM;

Наверх




Память: 0.57 MB
Время: 0.08 c
3-1158077928
Деня
2006-09-12 20:18
2006.11.12
Работа с типом INTERVAL


2-1162117932
Серый
2006-10-29 13:32
2006.11.12
Memo,ListBox,ComboBox


8-1142536058
softmaster
2006-03-16 22:07
2006.11.12
Работа с модемом


2-1161726522
Kostafey
2006-10-25 01:48
2006.11.12
Работа с датами в MS SQL Server


2-1161794659
redlord
2006-10-25 20:44
2006.11.12
кто вызвал появление popupmenu