powered by simpleCommunicator - 2.0.59     © 2025 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Игнорирование except блока
24 сообщений из 24, страница 1 из 1
Игнорирование except блока
    #40076232
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Есть такой код
Код: 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
Игнорирование except блока
    #40076236
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Так, первый кандидат есть. Здесь делают так
Код: plaintext
1.
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info);

sizeof(ULONG_PTR) - это 8 байт для x64. Но до этого все работало в том числе и на x64
...
Рейтинг: 0 / 0
Игнорирование except блока
    #40076238
Zelius
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Offtop
Автор знает про это ?
...
Рейтинг: 0 / 0
Игнорирование except блока
    #40076240
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
Игнорирование except блока
    #40076243
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сейчас проверил вот такой код в 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
Игнорирование except блока
    #40076258
GunSmoker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
А разница между первым и последним в чём?

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

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

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

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

И еще: вот полный код проекта
Код: 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
Игнорирование except блока
    #40076342
Фотография Кроик Семён
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_,

два вопроса

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




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



почему спрашиваю, ведь аргумент @LInfo ожидается массивом, т.е. все ячейки должны быть одного размера и без пропусков из-за выравнивания в record
...
Рейтинг: 0 / 0
Игнорирование except блока
    #40076348
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Итак код:
Код: 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
Игнорирование except блока
    #40076356
GunSmoker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
_Vasilisk_исключение вообще не поднимается и выделенная строка без вопросов выполняется. Имя потока тоже меняется
_Vasilisk_Запускаю из под отладчика
SetThreadName
OK

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

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

Воспроизводится. Надо глянуть...
...
Рейтинг: 0 / 0
Игнорирование except блока
    #40076358
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Совсем потерялся. На 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
Игнорирование except блока
    #40076370
GunSmoker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Короче, это баг в 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
Игнорирование except блока
    #40076387
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
GunSmoker
это баг в RTL Delphi
Ты на какой Delphi проверял? На последней?

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

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



случаем не должно быть
Код: pascal
1.
RaiseException($01010101, 0, 3, @LInfo[0]);
...
Рейтинг: 0 / 0
Игнорирование except блока
    #40076393
Фотография Кроик Семён
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
а стоп, глупость сморозил, думал о типе string
...
Рейтинг: 0 / 0
Игнорирование except блока
    #40076394
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Кроик Семён
может путаю, но вот это
Массив статический. Это одно и то же
...
Рейтинг: 0 / 0
Игнорирование except блока
    #40076397
GunSmoker
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
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
Игнорирование except блока
    #40076445
white_nigger
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Оформляй, может под тестирование бетт 10.5 решат/успеют пофиксить
...
Рейтинг: 0 / 0
Игнорирование except блока
    #40076449
Фотография _Vasilisk_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
24 сообщений из 24, страница 1 из 1
Форумы / Delphi [игнор отключен] [закрыт для гостей] / Игнорирование except блока
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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