Есть Assert в Dll с которой exe общается через интерфесы.
Почему Assert в DLL под отладчиком работает как надо, а без него (под ОС) срабатывает как тихое исключение (Abort) - и ничего не пишет и не выводит.
В exe ассерт работает правильно.
Уважаемые авторы вопросов! Большая просьба сообщить о результатах решения проблемы на этой странице. Иначе, следящие за обсуждением, возможно имеющие аналогичные проблемы, не получают ясного представления об их решении. А авторы ответов не получают обратной связи. Что можно расценивать, как проявление неуважения к отвечающим от автора вопроса.
16-05-2009 13:09 | Комментарий к предыдущим ответам
Вопрос не рассчитан на гадание и сходу его не решишь
Гадать тут нечего и решать тоже нечего, все уже давно решено. DLL тут абсолютно ни при чем. Запустите свой поток в EXE и получите то-же самое поведение. Так-же ничего не изменит замена Assert на любое другое исключение.
Вам уже объяснили, как обрабатываются исключения в доп. потоках, и что никакое исключение в доп. потоке не будет само сабой показано.
Работает корректно:
...
3.Если вызван в dll НЕ в основном потоке, под отладчиком
Работат как Abort (не показывая сообщения)
1. Если вызван в другом потоке в DLL (под OS только)
Уберите в опциях отладчика птицу Stop on Delphi Exceptions и будет у Вас все одинаково.
22-07-2008 11:47 | Комментарий к предыдущим ответам
Да ну? EAssertionFailed - это не исключение, что-ли?
Вы не поняли. Не в этом плане. Это относится к
Если вы ждёте, что при этом будет показано какое-либо сообщение, то вам это нужно сделать руками (Exception),
Поэтому я попросил вас отличать исключение от ассерта.
Поэтому: не могли бы вы всё же привести код;
Все совершенно стандартное.
Создается DLL, создаем стандартный поток.
В нем вызываем Assert (False) - больше ничего.
где у вас стоит обработка исключений и показ сообщений и т.п.
Нет там ничего кроме строки Assert(false) .
Вопрос не рассчитан на гадание и сходу его не решишь, а рассчитан именно на то что возможно кто то с этим встречался - т.к. ситуация осована на стандартных условиях, либо хорошо разбирается в низкоуровневых модулях.
>>> Не путайте исключения и ассерты пожалуйста.
Да ну? EAssertionFailed - это не исключение, что-ли?
Не могли бы вы всё же дать больше информации?
Посмотрите на Assert:
procedure _Assert(const Message, Filename: AnsiString; LineNumber: Integer);
begin
if Assigned(AssertErrorProc) then
AssertErrorProc(Message, Filename, LineNumber, Pointer(-1))
else
Error(reAssertionFailed); // loses return address
end;
Т.е. он просто вызывает AssertErrorProc, который равен (вы ведь используете SysUtils?):
procedure AssertErrorHandler(const Message, Filename: string;
LineNumber: Integer; ErrorAddr: Pointer);
var
E: Exception;
begin
E := CreateAssertException(Message, Filename, LineNumber);
RaiseAssertException(E, ErrorAddr, PChar(@ErrorAddr)+4);
end;
Который просто создаёт исключение. Причём EAssertionFailed не относится к тихим исключениям.
Отсюда следует, что если подключен SysUtils и Assert-ы включены, то любой неудачный Assert приводит к возникновению исключения вне зависимости от того, находится ли он в DLL или в EXE. И уж тем более, от того, в каком потоке вызывается.
Поэтому: не могли бы вы всё же привести код; рассказать, как создаёте поток; не находится ли код потока в отдельном модуле; что у вас с опциями проекта (Assertions) и не стоят ли эти директивы в коде; как вы определили, что Assert там вообще есть и он срабатывает; где у вас стоит обработка исключений и показ сообщений и т.п. Ну поверьте же, что здесь не телепаты сидят.
P.S.
>>> Кстати в вашем примере две ошибки. :)
Если вы про Synchronize, то - да, согласен, нужно было это указать. Поленился. Просто хотел подтолкнуть вас к тому, чтобы вы излагали больше информации.
22-07-2008 09:06 | Комментарий к предыдущим ответам
Можете подробнее описать, что вы делаете, что при этом происходит, и, в частности, чего вы ожидаете.
Я просто вызываю Assert(false) - для проверки.
Если я запускаю программу из под отладчика, - ассерт отображается в виде диалога, т.е. как и положено.
Если же запускаю с под ОС - тогда он работает как Abort (Silent exception) - не отображая сообщение.
Еще раз:
Работает корректно:
1.Если вызван в exe (OS и отладчик)
2.Если вызван в dll но в основном потоке. (OS и отладчик)
3.Если вызван в dll НЕ в основном потоке, под отладчиком.
Работат как Abort (не показывая сообщения)
1. Если вызван в другом потоке в DLL (под OS только)
Если вы ждёте, что при этом будет показано какое-либо сообщение, то вам это нужно сделать руками,
Я это прекрасно знаю. Не путайте исключения и ассерты пожалуйста.
Предварительно: любое исключение в потоке приводит к его остановке. Если используется TThread, то исключение помещается в свойство FatalException. Если вы ждёте, что при этом будет показано какое-либо сообщение, то вам это нужно сделать руками, например:
procedure TMyThread.Execute;
begin
try
...
except
on E: Exception do
begin
ShowMessage(E.Message);
end;
end;
end;
Не путайте возможность отладчика показывать предварительное уведомление об исключении с реальной раскруткой и обработкой ошибок в программе.
Если вы заметили орфографическую ошибку на этой странице, просто выделите ошибку мышью и нажмите Ctrl+Enter. Функция может не работать в некоторых версиях броузеров.