powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Исключение в MoveTo
25 сообщений из 83, страница 2 из 4
Исключение в MoveTo
    #39597014
Соколинский Борис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
makhaonБуду благодарен за идеи. Не знаю, поможет или нет.
Сравнительно недавно обнаружил, что при пересоздании окна treeview все адреса node-ов меняются. Возможно, что-то такое имеет место.
...
Рейтинг: 0 / 0
Исключение в MoveTo
    #39597041
white_nigger
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Компилятор тоже человек :) У нас до сих пор танцы с бубнами бывают при вызовах делфовых методов из билдера. Не так давно секс с nullable был. Билдер при использовании в 32-битах неправильно адреса полей генерил, в 64-битах работало нормально. Хз почему ассемблерный выхлоп по разному генерился
...
Рейтинг: 0 / 0
Исключение в MoveTo
    #39597042
white_nigger
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
*для делфей и билдера в 32-битах
...
Рейтинг: 0 / 0
Исключение в MoveTo
    #39597076
GunSmoker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Товарищи, там дизасм от EurekaLog, она трейсит в обратную сторону . Поэтому возможно неверное определкние границ команд.
...
Рейтинг: 0 / 0
Исключение в MoveTo
    #39597080
Фотография makhaon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Соколинский Борис,

Вообще то часть костылей как раз связана с изменением адресов нод. И вроде бы частично помогло, падало по-другому, с nil'ом. У меня есть подозрение, что виновата винда, меняя адреса нод 'на лету'. Сам я ни окно ни дерево не пересоздаю. Окно - главное окно программы, не нем дерево лежит. Ноды, бывает, удаляются, но только уже из History, после MoveTo.

По asm дампу: да, возможно эвкрика не совсем верный дамп показала.
...
Рейтинг: 0 / 0
Исключение в MoveTo
    #39597081
Фотография makhaon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Пока что сделал так:

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
{$O-}
          Test1 := Session.NodeFields;
          Test2 := Test1.RootNode;
          MoveToHistory(Test2, Node);
{$O+}

// + локальная процедура в модуле:

{$O-}
procedure MoveToHistory(Node, Node2: TTreeNode);
begin
 Node.MoveTo(Node2, naAddChild);
end;
{$O+}



Поставлю на тест, посмотрю, что получится.
...
Рейтинг: 0 / 0
Исключение в MoveTo
    #39597082
Соколинский Борис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
makhaonУ меня есть подозрение, что виновата винда, меняя адреса нод 'на лету'.Это легко проверить: сделай expect-блок и в нем сбрасывай в xml-лог все узлы с адресами.
...
Рейтинг: 0 / 0
Исключение в MoveTo
    #39597084
GunSmoker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Дизасм от Delphi:

автор488B85F0010000 mov rax,[rbp+$000001f0]
488B80B8000000 mov rax,[rax+$000000b8]
488B8838050000 mov rcx,[rax+$00000538]
488B85F0010000 mov rax,[rbp+$000001f0]
488B90D0000000 mov rdx,[rax+$000000d0]
E8C8E8A7FF call $000000000012d4c0
488985A0010000 mov [rbp+$000001a0],rax
4883BDA001000000 cmp qword ptr [rbp+$000001a0],$00
74AD jz $00000000006aebb6
488B85C8010000 mov rax,[rbp+$000001c8]
488B4028 mov rax,[rax+$28]
4889C1 mov rcx,rax
488B95A0010000 mov rdx,[rbp+$000001a0]
41B002 mov r8b,$02
488B18 mov rbx,[rax]
FF5320 call qword ptr [rbx+$20]
...
Рейтинг: 0 / 0
Исключение в MoveTo
    #39597119
Фотография JayDi
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
То, что к моменту MoveTo данные уже испорчены и ошибка с лишним Free (или любой другой операции записи в память) была в совсем другом месте -- уже не рассматривается?
...
Рейтинг: 0 / 0
Исключение в MoveTo
    #39597121
Arioch_really
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
GunSmoker,

Ух ты, в кои-то веки встроенный дизасм лучше стороних утилит!
...
Рейтинг: 0 / 0
Исключение в MoveTo
    #39597122
kep-ko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
makhaon,
Другие части кода, скорее всего, не причастны,
есть подозрение, что виновата винда


Код: pascal
1.
Access violation at address 0000000000D0F2D4 in module 'Project1.exe'. Read of address FFFFFFFFFFFFFFFF.



Код: plaintext
1.
2.
3.
4.
5.
6.
mov rax,[rbp+$000001c8]  // что-то много на стеке, возможно буфер, за который кто-то вылазит, возможно в другом потоке, из-за чего фантомность ошибки - колись )
mov rax,[rax+$28]
mov rcx,rax
mov rdx,[rbp+$000001a0]
mov r8b,$02
mov rbx,[rax]
0000000000D0F2D4 call qword ptr [rbx+$20]
...
Рейтинг: 0 / 0
Исключение в MoveTo
    #39597132
Arioch_Really
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
в конвенции Win64 первый четыре параметра передаются в регистрах RCX, RDX, R8, R9
https://en.wikipedia.org/wiki/X86_calling_conventions#Microsoft_x64_calling_convention

Self^ указывает на таблицу VMT
http://docwiki.embarcadero.com/RADStudio/Tokyo/en/Internal_Data_Formats_(Delphi)#Class_Types

Session.NodeFields.RootNode.MoveTo(Node, naAddChild);
Параметры:
1) Self = RootNode = RCX
2) (Target) = Node = RDX
3) naAddChild = byte(R8)

код в обратном порядке

Код: asm
1.
2.
3.
4.
5.
6.
7.
call qword ptr [rbx+$20]    ' вызов виртуального метода, вероятно №6 (32/8+1)  из @VMT=Self^=RBX
mov rbx,[rax]                  ' загрузка адреса VMT как первого указателя по адресу Self^ ( aka Self[0] ); RAX = RootNode
mov r8b,$02                    ' загрузка константы в 3-1 аргумент метода
mov rdx,[rbp+$000001a0]  ' загрузка адреса "целевой" ноды из локальной переменной во второй аргумент
mov rcx,rax                     ' загрузка Self вызываемого объекта в первый параметр, RAX = RootNode
mov rax,[rax+$28]            ' загрузка RootNode в RAX; перед этим RAX = NodeFields и RootNode если внутренняя (member) переменная
mov rax,[rbp+$000001c8]  ' загрузка NodeFields из локальной переменной в RAX


Вангую, что Session - это какая-то развесистая локальная переменная типа record, возможно содержащая буфер или рядом с буфером.

Больше инфы в самом деле хотелось бы про процедуру, в которой сбой происходит.

Если там есть буферы - предлагаю вокруг них гарды поставить. И/или поставить гарды вокруг переменной Session.Nodefields
Если кто-то в самом деле затирает чужую память, не адресно выстрелил и попал, а размашисто разогнался и не успел остановиться, то гарды он по идее тоже должен будет снести и в memory dump стэка это будет заметно

можно предположить use after free, но тогда обычно память при освобождение забивают чем-то более забойным, чем -1

Пока мне кажется, что происходит корерктной получения указателя на VMT - а вот дальше адрес метода оказывается -1

Почему, что это значит - хз. Может быть так абстрактные методы обозначаются? Информации не нашёл сходу.
Но вот интересный момент: http://members.tripod.com/~s_mathur/Virt.html
Смотрим на второй дамп, это как раз VMT (или в терминах Visual C++, V-table).
В классе есть только одна виртуальная функция - и первые 4 байта VMT заполнены
А вот дальше идёт FF-FF-FF-FF - та самая минус единица.
То ли добивают размер VMT до кратного 8, либо после последней "легитимной" функции в качестве маркера ставят "якобы еще один метод" с адресом -1

Если так предположить, то похоже иногда в переменной Session.NodeFields.RootNode оказывается указатель не на TNode (или что там должно быть), а на объект какого-то другого класса, например предка или вообще от фонаря какого-нибудь, и у этого другого класса 5 либо меньше виртуальных методов и никакого метода №6 (MoveTo) у него вообще нет (или м.б. абстрактный????).

В общем, в порядке параной перед выводом MoveTo пробуй проверить какого типа там хрень лежит, возможно иногда совсем не того, который ты ожидаешь
...
Рейтинг: 0 / 0
Исключение в MoveTo
    #39597137
Arioch_Truly
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
makhaon Сам я ни окно ни дерево не пересоздаю.

.RecreateWnd никто не отменял при изменении настроек контрола или окна, которые можно менят ьв VCL и нельзя в Windows GDI API

Меня в свое время СИЛЬНО ругали на Stack Overflow за передачу TForm.Handle в поток, хотя лёгкой практической альтернативы так и не предложили. Говорили, дескать, по любому чиху у главной формы поменяется Handle и будет мой поток PostMessage на деревню дедушке слать.

Предложение - вообще НЕ передавать в поток никаких указателей на объекты.
Высылать команды, например "Ноду с ID=xxxx переместить под ноду с ID=yyyy"
Что у тебя в контексте твоей задачи будет логический ID ноды - тебе виднее.

Такие команды можно высылать например через PostMessage на специально для того заведённое невидимое окно (CreateHWND).
Или использовать глобальную переменную с синглтоном TThreadList<TmyCommandRecord>
Или коллекцию из OmniThreadLibrary

В общем, рабочий поток НЕ пользуется синхронайзом, а посылает в VCL-поток команды семантические, в терминах задачи, а не контролов.
А уже сама форма, в VCL-потоке, когда до нее доберётся это сообщение, поймёт что нужно найти две ноды по ID и поместить одну внутрь другой.
Геморроя прописывать явно все виды "семантических" сообщений может быть много. Зато изоляция, потом например сможешь поменять TTreeView на TVirtualTreeview или VCL на FMX и "рабочие" потоки вообще это никак не заденет.
...
Рейтинг: 0 / 0
Исключение в MoveTo
    #39597140
Соколинский Борис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arioch_TrulyМеня в свое время СИЛЬНО ругали на Stack Overflow за передачу TForm.Handle в поток, хотя лёгкой практической альтернативы так и не предложили.

Элементарно, Ватсон.
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
type
IWndHandler=interface
[какой-то гуид]
function GetHandle: hwnd; 
property Handle: hwnd read GetHandle;
end;

TWndHandler=class(TInterfacedObject, IWndHandler)
private
  FControl: TWinControl;
protected
  function GetHandle: Hwnd;
{ begin result:=FControl.Handle; end;}
public
  constructor Create(AControl: TWinControl);
end;


IWndHandler передаешь в поток.
...
Рейтинг: 0 / 0
Исключение в MoveTo
    #39597143
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Соколинский БорисЭлементарноЯ бы так не сказал.

Если хэндл имеет тенденцию меняться, то нужна какая-то синхронизация. Это раз.

Вызов TWinControl.GetHandle может спровоцировать HandleAllocate и создание окна в другом потоке
...
Рейтинг: 0 / 0
Исключение в MoveTo
    #39597145
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Подозреваю, что один из самых простых способов - это передавать в поток ThreadID главного потока, а в потоке дергать PostThreadMessage. Для синхронных сообщений пишется небольшая обвязка
...
Рейтинг: 0 / 0
Исключение в MoveTo
    #39597146
fd00ch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Arioch_TrulyМеня в свое время СИЛЬНО ругали на Stack Overflow за передачу TForm.Handle в поток, хотя лёгкой практической альтернативы так и не предложили. Говорили, дескать, по любому чиху у главной формы поменяется Handle и будет мой поток PostMessage на деревню дедушке слать.правильно ругали, AllocateHWnd же есть
...
Рейтинг: 0 / 0
Исключение в MoveTo
    #39597150
kep-ko
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Arioch_Truly, @offtop
Говорили, дескать, по любому чиху у главной формы поменяется Handle и будет мой поток PostMessage на деревню дедушке слать.
Ребятам по молодости сказали кушай как-тус, а теперь чтоб в седую бороду не признаваться, что подкол не поняли, так дальше муть и разливают.
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
procedure TWinControl.HandleNeeded;
begin
  if WindowHandle = 0 then
  begin
    if Parent <> nil then Parent.HandleNeeded;
    CreateHandle;
  end;
end;

function TWinControl.GetHandle: HWND;
begin
  HandleNeeded;
  Result := WindowHandle;
end;
...
Рейтинг: 0 / 0
Исключение в MoveTo
    #39597152
Соколинский Борис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,
Можно проверять HandleAllocated. А в синхронизации необходимости не вижу.
...
Рейтинг: 0 / 0
Исключение в MoveTo
    #39597153
YuRock
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Соколинский Борис_Vasilisk_,
Можно проверять HandleAllocated. А в синхронизации необходимости не вижу.Ну. И если оно = False - что дальше?
...
Рейтинг: 0 / 0
Исключение в MoveTo
    #39597155
Соколинский Борис
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
YuRock,
Вернуть 0. В потоке - если нужна синхронная обработка - подождать, Нет - послать позже.
...
Рейтинг: 0 / 0
Исключение в MoveTo
    #39597427
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
fd00chправильно ругали, AllocateHWnd же есть

К нему нет обвязки, сравнимой по удобству с созданием метода TMainForm.OnMySuperMessage
...
Рейтинг: 0 / 0
Исключение в MoveTo
    #39597432
Arioch
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
kep-ko,

я знаю этот кусок :-)

Соколинский БорисМожно проверять HandleAllocated. А в синхронизации необходимости не вижу.

1) .....вот когда при напряжной работе Хэндл убьётся сразу после проверки HandleAllocated..... Хотя, конечно, можно сам объект формы поточно лочить, но в Delphi RTL TMonitor.Lock (кажется) реализован довольно медленно
2) про False уже сказали
...
Рейтинг: 0 / 0
Исключение в MoveTo
    #39597549
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
AriochК нему нет обвязки,Написать обвязку - полминуты и пять строк кода
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
procedure TForm1.GetWindow: HWND;
begin
  CheckMainThread;
  if FWindow = 0 then
    FWindow := AllocateHWnd(InternalWndProc);
  Result := FWindow;
end;

procedure TForm1.InternalWndProc(var AMessage: TMessage);
begin
  Dispatch(AMessage);
end;
...
Рейтинг: 0 / 0
Исключение в MoveTo
    #39598378
Фотография makhaon
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Новые данные.
Что сделал. Удалось отказаться от доп. потока и сделать выполнение процедуры в основном потоке, по событию таймера.
На баг никак не повлияло. Исключение то же. Колл-стэк завёл в процедуру MoveToHistory, то есть до этого не свалилось.

Вот ассемблерный дамп эврики (к слову - с большим трудом нашел как его скопировать из вьювера. вообще - во вьювере есть несколько неудобств):

автор; Base Address: $D0E000, Allocation Base: $400000, Region Size: 5046272
; Allocation Protect: PAGE_EXECUTE_WRITECOPY, Protect: PAGE_EXECUTE_READ
; State: MEM_COMMIT, Type: MEM_IMAGE
;
;
; EPSessionManager.MoveToHistory (Line=455 - Offset=0)
; ----------------------------------------------------
0000000000D0E760 55 PUSH RBP
0000000000D0E761 53 PUSH RBX
0000000000D0E762 4883EC28 SUB RSP, $28
0000000000D0E766 488BEC MOV RBP, RSP
0000000000D0E769 48894D40 MOV [RBP+$40], RCX
0000000000D0E76D 48895548 MOV [RBP+$48], RDX
;
; Line=456 - Offset=17
; --------------------
0000000000D0E771 488B4D40 MOV RCX, [RBP+$40]
0000000000D0E775 488B5548 MOV RDX, [RBP+$48]
0000000000D0E779 41B002 MOV AL, 2
0000000000D0E77C 488B4540 MOV RAX, [RBP+$40]
0000000000D0E780 488B18 MOV RBX, [RAX]
;
; Line=456 - Offset=35
; --------------------
0000000000D0E783 FF5320 CALL QWORD PTR [RBX+$20] ; <-- EXCEPTION
;
; Line=457 - Offset=38
; --------------------
0000000000D0E786 488D6528 LEA RSP, [RBP+$28]
0000000000D0E78A 5B POP RBX
0000000000D0E78B 5D POP RBP
...
Рейтинг: 0 / 0
25 сообщений из 83, страница 2 из 4
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Исключение в MoveTo
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]