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

Вниз

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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.56 MB
Время: 0.041 c
15-1161868276
Сергей М.
2006-10-26 17:11
2006.11.12
TRACE MODE 6


15-1162023689
Kerk
2006-10-28 12:21
2006.11.12
Знатокам phpBB


15-1161542096
Belorus
2006-10-22 22:34
2006.11.12
Профайлер...


4-1151082659
GrBob
2006-06-23 21:10
2006.11.12
Удаленное подключение к SCM


2-1162189560
Чайник2
2006-10-30 09:26
2006.11.12
Как перенести содержимое поля 1-й таблицы в поле другой?





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