Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Игнорирование except блока / 24 сообщений из 24, страница 1 из 1
07.06.2021, 21:10
    #40076232
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Игнорирование except блока
Есть такой код
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
const
  CExceptionCode = $406D1388;
type
  THREADNAME_INFO = record
    dwType: DWORD; // must be 0x1000
    szName: PUTF8String; // pointer to name (in user addr space)
    dwThreadID: DWORD; // thread ID (-1=caller thread)
    dwFlags: DWORD; // reserved for future use, must be zero
  end;

procedure SetThreadName(AThreadID: Cardinal; const AName: string);
var
  LInfo: THREADNAME_INFO;
begin
  LInfo.dwType := $1000;
  LInfo.szName := PUTF8String(UTF8String(AName));
  LInfo.dwThreadID := AThreadID;
  LInfo.dwFlags := 0;
  try
    RaiseException(CExceptionCode, 0, SizeOf(LInfo) div SizeOf(DWORD), @LInfo);
  except
    on E: EExternalException do
      if E.ExceptionRecord^.ExceptionCode <> CExceptionCode then
        raise;
  end;
end;

В последнее время в логе стала появляться надписьExternal exception 406D1388Т.е. исключение выходит из этой процедуры и отлавливается вышестоящим обработчиком. Вопрос: как такое может происходить?

Модуль не менялся с августа 2019. Скомпилирован на XE3 под Win64 и до этого работало как часы.

Есть глупое предположение, что что-то поломалось с обновлением Windows, но это из разряда предположить хоть что-нибудь.


С уважением, Vasilisk
...
Рейтинг: 0 / 0
07.06.2021, 21:28
    #40076236
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Игнорирование except блока
Так, первый кандидат есть. Здесь делают так
Код: plaintext
1.
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info);

sizeof(ULONG_PTR) - это 8 байт для x64. Но до этого все работало в том числе и на x64
...
Рейтинг: 0 / 0
07.06.2021, 21:38
    #40076238
Zelius
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Игнорирование except блока
Offtop
Автор знает про это ?
...
Рейтинг: 0 / 0
07.06.2021, 21:46
    #40076240
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Игнорирование except блока
Zelius
Автор знает про это ?
Знает. Когда писался этот код стандартного еще не было.

К слову, в Rio почти такая же реализация, кроме того, что отлавливаются все исключения
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
class procedure TThread.NameThreadForDebugging(AThreadName: string; AThreadID: TThreadID);
{$IF Defined(MSWINDOWS)}
type
  TThreadNameInfo = record
    FType: LongWord;     // must be 0x1000
    FName: MarshaledAString;    // pointer to name (in user address space)
    FThreadID: LongWord; // thread ID (-1 indicates caller thread)
    FFlags: LongWord;    // reserved for future use, must be zero
  end;
var
  ThreadNameInfo: TThreadNameInfo;
  M:TMarshaller;
begin
  if IsDebuggerPresent then
  begin
    ThreadNameInfo.FType := $1000;
    ThreadNameInfo.FName := M.AsAnsi(AThreadName).ToPointer;
    ThreadNameInfo.FThreadID := AThreadID;
    ThreadNameInfo.FFlags := 0;

    try
      RaiseException($406D1388, 0, sizeof(ThreadNameInfo) div sizeof(LongWord), @ThreadNameInfo);
    except
    end;
  end;
end;
...
Рейтинг: 0 / 0
07.06.2021, 22:02
    #40076243
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Игнорирование except блока
Сейчас проверил вот такой код в XE3 и Rio при компиляции под Win64
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
procedure SetThreadName(AThreadID: Cardinal; const AName: string);
var
  LInfo: THREADNAME_INFO;
begin
  LInfo.dwType := $1000;
  LInfo.szName := PUTF8String(UTF8String(AName));
  LInfo.dwThreadID := AThreadID;
  LInfo.dwFlags := 0;
  RaiseException(CExceptionCode, 0, SizeOf(LInfo) div SizeOf(DWORD), @LInfo);
  LInfo.dwFlags := 555;
end;

исключение вообще не поднимается и выделенная строка без вопросов выполняется. Имя потока тоже меняется
...
Рейтинг: 0 / 0
07.06.2021, 23:33
    #40076258
GunSmoker
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Игнорирование except блока
А разница между первым и последним в чём?

Векторные обработчики никто, случаем, не ставит?
...
Рейтинг: 0 / 0
08.06.2021, 11:43
    #40076320
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Игнорирование except блока
GunSmoker
А разница между первым и последним в чём?
Полное отсутствие блока try..except
GunSmoker
Векторные обработчики никто, случаем, не ставит?
Санкционировано нет. Вроде джедаи что-то пытаются, но при их отключении ничего не меняется.

Основной вопрос - почему исключение вываливается наружу? И почему я такого поведения не вижу у себя?
...
Рейтинг: 0 / 0
08.06.2021, 11:50
    #40076322
Кроик Семён
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Игнорирование except блока
_Vasilisk_,

предположения:

1) E не типа EExternalException
2) E.ExceptionRecord^.ExceptionCode <> CExceptionCode
...
Рейтинг: 0 / 0
08.06.2021, 11:53
    #40076325
Мимопроходящий
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Игнорирование except блока
_Vasilisk_, логируй таки действительный класс исключения.
Posted via ActualForum NNTP Server 1.5
...
Рейтинг: 0 / 0
08.06.2021, 11:55
    #40076327
Кроик Семён
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Игнорирование except блока
P.S.
а ещё у меня было: исключения игнорировались когда портилась память (запись по неинициализированному указателю)
...
Рейтинг: 0 / 0
08.06.2021, 12:11
    #40076333
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Игнорирование except блока
Кроик Семён
предположения:
Допустим. Хотя сообщение вот такое

И еще: вот полный код проекта
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
program Test;

{$APPTYPE CONSOLE}

uses
  Winapi.Windows,
  System.SysUtils;

const
  CExceptionCode = $406D1388;
type
  THREADNAME_INFO = record
    dwType: DWORD; // must be 0x1000
    szName: PUTF8String; // pointer to name (in user addr space)
    dwThreadID: DWORD; // thread ID (-1=caller thread)
    dwFlags: DWORD; // reserved for future use, must be zero
  end;

procedure SetThreadName(AThreadID: Cardinal; const AName: string);
var
  LInfo: THREADNAME_INFO;
begin
  LInfo.dwType := $1000;
  LInfo.szName := PUTF8String(UTF8String(AName));
  LInfo.dwThreadID := AThreadID;
  LInfo.dwFlags := 0;
//  try
    RaiseException(CExceptionCode, 0, SizeOf(LInfo) div SizeOf(DWORD), @LInfo);
//  except
//    on E: EExternalException do
//      if E.ExceptionRecord^.ExceptionCode <> CExceptionCode then
//        raise;
//  end;
end;

begin
  SetThreadName(GetCurrentThreadId, 'Main');
  Writeln('Done');
  Readln;
end.

try..except закомментирован. В консоль выводится Done. Почему?
Кроик Семён
а ещё у меня было: исключения игнорировались когда портилась память
У меня это происходит при старте службы, когда одновременно запускается несколько потоков. Как бы этот код работал годами
...
Рейтинг: 0 / 0
08.06.2021, 12:37
    #40076342
Кроик Семён
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Игнорирование except блока
_Vasilisk_,

два вопроса

1)
Код: pascal
1.
SizeOf(PUTF8String) == SizeOf(DWORD) // ??????




2)
Код: pascal
1.
SizeOf(THREADNAME_INFO) // меняется ли, если его сделать packed record вместо record ??????



почему спрашиваю, ведь аргумент @LInfo ожидается массивом, т.е. все ячейки должны быть одного размера и без пропусков из-за выравнивания в record
...
Рейтинг: 0 / 0
08.06.2021, 12:54
    #40076348
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Игнорирование except блока
Итак код:
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
35.
36.
37.
38.
39.
40.
41.
42.
43.
44.
45.
46.
47.
48.
49.
program Test;

{$APPTYPE CONSOLE}

uses
  Winapi.Windows,
  System.SysUtils;

const
  CExceptionCode = $406D1388;
type
  THREADNAME_INFO = record
    dwType: DWORD; // must be 0x1000
    szName: PUTF8String; // pointer to name (in user addr space)
    dwThreadID: DWORD; // thread ID (-1=caller thread)
    dwFlags: DWORD; // reserved for future use, must be zero
  end;

procedure SetThreadName(AThreadID: Cardinal; const AName: string);
var
  LInfo: THREADNAME_INFO;
begin
  LInfo.dwType := $1000;
  LInfo.szName := PUTF8String(UTF8String(AName));
  LInfo.dwThreadID := AThreadID;
  LInfo.dwFlags := 0;
  try
    RaiseException(CExceptionCode, 0, SizeOf(LInfo) div SizeOf(ULONG_PTR), @LInfo);
  except
    on E: EExternalException do begin
      Writeln('Internal catched ', IntToHex(E.ExceptionRecord^.ExceptionCode, 8));
      if E.ExceptionRecord^.ExceptionCode <> CExceptionCode then
        raise;
    end;
  end;
end;

begin
  try
    Writeln('SetThreadName');
    SetThreadName(GetCurrentThreadId, 'Main');
    Writeln('OK');
  except
    on E: Exception do begin
      Writeln(Format('Class: %s, %s, Msg: %s', [E.ClassName, BoolToStr(E is EExternalException, True), E.Message]));
    end;
  end;
  Readln;
end.

Запускаю из под отладчика
SetThreadName
OK
Запускаю не из под отладчика, но скомпилированное под Win32SetThreadName
Internal catched 406D1388
OK
Запускаю не из под отладчика Win64 приложениеSetThreadName
Internal catched 00000000
Class: EExternalException, True, Msg: External exception 406D1388
И как к этому относиться?

Сделал логирование ExceptionRecord
Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
LRec := E.ExceptionRecord;
Writeln(Format(
  'Code: %.8x, Flags: %.8x, Record: %p, Addr: %p, ParamCount: %u',
  [
    LRec^.ExceptionCode,
    LRec^.ExceptionFlags,
    LRec^.ExceptionRecord,
    LRec^.ExceptionAddress,
    LRec^.NumberParameters
  ]
));

Получил такоеCode: 00000000, Flags: 00000000, Record: 000000000042E398, Addr: 000000000014FDD0, ParamCount: 4217187Явный мусор.

Компилировал и в XE3 и в Rio
...
Рейтинг: 0 / 0
08.06.2021, 13:05
    #40076356
GunSmoker
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Игнорирование except блока
_Vasilisk_исключение вообще не поднимается и выделенная строка без вопросов выполняется. Имя потока тоже меняется
_Vasilisk_Запускаю из под отладчика
SetThreadName
OK

Запускаю не из под отладчика
SetThreadName
Internal catched 406D1388
OK

Ну это как раз "as designed". Возбуждение исключения - это сигнал отладчику. Если он подключён - он обрабатывает исключение сразу. Если отладчика нет - то некому обработать исключение, вот оно до except и поднимается.
...
Рейтинг: 0 / 0
08.06.2021, 13:08
    #40076357
GunSmoker
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Игнорирование except блока
_Vasilisk_SetThreadName
Internal catched 00000000
Class: EExternalException, True, Msg: External exception 406D1388

Воспроизводится. Надо глянуть...
...
Рейтинг: 0 / 0
08.06.2021, 13:09
    #40076358
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Игнорирование except блока
Совсем потерялся. На Win2008 вот такой код
Код: pascal
1.
2.
3.
4.
5.
on E: EExternalException do begin
  Writeln('Internal catched ', IntToHex(E.ExceptionRecord^.ExceptionCode, 8), ', Dec: ', E.ExceptionRecord^.ExceptionCode);
  LRec := E.ExceptionRecord;
  Writeln(Format('Code: %.8x', [LRec^.ExceptionCode]));
end;

Выводит три различных значения. Как это? Приложение все то же - консольное однопоточное
...
Рейтинг: 0 / 0
08.06.2021, 13:28
    #40076370
GunSmoker
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Игнорирование except блока
Короче, это баг в RTL Delphi. Пиши в QC.

Код: pascal
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
32.
33.
34.
program Test;

{$APPTYPE CONSOLE}

uses
  Winapi.Windows,
  System.SysUtils;

procedure Test;
var
  LInfo: array[0..2] of NativeUInt;
begin
  try
    // Any exception code and any args
    LInfo[0] := 1;
    LInfo[1] := 2;
    LInfo[2] := 3;
    RaiseException($01010101, 0, 3, @LInfo);
  except
    on E: EExternalException do begin
      // Outputs trash
      Writeln('ExceptionCode: ', IntToHex(E.ExceptionRecord^.ExceptionCode, 8));
      Writeln('NumberParameters: ', IntToStr(E.ExceptionRecord^.NumberParameters));
      Writeln('ExceptionInformation[0]: ', IntToStr(E.ExceptionRecord^.ExceptionInformation[0]));
      Writeln('ExceptionInformation[1]: ', IntToStr(E.ExceptionRecord^.ExceptionInformation[1]));
      Writeln('ExceptionInformation[2]: ', IntToStr(E.ExceptionRecord^.ExceptionInformation[2]));
    end;
  end;
end;

begin
  Test;
  Readln;
end.
...
Рейтинг: 0 / 0
08.06.2021, 13:50
    #40076387
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Игнорирование except блока
GunSmoker
это баг в RTL Delphi
Ты на какой Delphi проверял? На последней?

Если я скажу, что до этого код работал. Могло такое быть?
...
Рейтинг: 0 / 0
08.06.2021, 13:50
    #40076388
Кроик Семён
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Игнорирование except блока
GunSmoker,

может путаю, но вот это
Код: pascal
1.
RaiseException($01010101, 0, 3, @LInfo);



случаем не должно быть
Код: pascal
1.
RaiseException($01010101, 0, 3, @LInfo[0]);
...
Рейтинг: 0 / 0
08.06.2021, 13:54
    #40076393
Кроик Семён
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Игнорирование except блока
а стоп, глупость сморозил, думал о типе string
...
Рейтинг: 0 / 0
08.06.2021, 13:54
    #40076394
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Игнорирование except блока
Кроик Семён
может путаю, но вот это
Массив статический. Это одно и то же
...
Рейтинг: 0 / 0
08.06.2021, 14:00
    #40076397
GunSmoker
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Игнорирование except блока
10.3 Rio, не вижу смысла проверять где-то ещё, если ты говоришь, что аж в XE3 это воспроизводится. Очевидно, никто это не проверял.

_Vasilisk_Если я скажу, что до этого код работал. Могло такое быть?

Вполне. "Если код работает - это не значит, что он правильный".

Я глубоко не копал, но там ExceptionRecord передаётся по указателю:
Код: pascal
1.
2.
3.
    E := EExternalException.CreateFmt(SExternalException, [P.ExceptionCode]);
  end;
  if E is EExternal then EExternal(E).ExceptionRecord := P;


Заметь, что в объекте Delphi правильно указывается код исключения ('External exception 01010101'), но при этом в ER - мусор. Т.е. в объекте Delphi сохраняется указатель на временное положение ER на стеке. Тогда при дальнейшем выполнении тут будет "как повезёт".
...
Рейтинг: 0 / 0
08.06.2021, 15:47
    #40076445
white_nigger
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Игнорирование except блока
Оформляй, может под тестирование бетт 10.5 решат/успеют пофиксить
...
Рейтинг: 0 / 0
08.06.2021, 15:58
    #40076449
_Vasilisk_
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Игнорирование except блока
...
Рейтинг: 0 / 0
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Игнорирование except блока / 24 сообщений из 24, страница 1 из 1
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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