Как получить трассировку стека из обработанного / перехваченного исключения и вывести его в журнал трассировки - PullRequest
4 голосов
/ 15 декабря 2011

Мы создали службу Datasnap (с Delphi XE), используя в качестве руководства белую бумагу Боба Сварта.Он работает нормально, и мы развернули его на нашем тестовом сервере.

Теперь возникает проблема, когда мы выполнили большое количество запросов (через JMeter), происходит какое-то повреждение памяти.Некоторые запросы выполняются успешно, некоторые - с нарушением прав доступа.В конце концов, он стал настолько испорченным, что каждый запрос к нашим СОБСТВЕННЫМ (не DSAdmin) методам отвечает нарушением доступа.

Однако я не могу достать трассировку стека для получения дополнительной информации, поскольку исключение уже перехватывается при обработке запроса.

Если я интенсивно тестирую с версией VCLэтого приложения, оно продолжает работать правильно.

Кто-нибудь знает, что это может быть, испытывает ту же проблему, или вы можете помочь мне получить трассировку стека от пойманного исключения (в чужом коде,Я не могу редактировать)?

Заранее спасибо.

Ответы [ 2 ]

7 голосов
/ 17 декабря 2011

Чтобы регистрировать как пойманные, так и неперехваченные исключения с помощью JEDI JCL, вы должны установить JEDI JCL .

Затем попробуйте какой-нибудь код, подобный этому, взятому из jcl\examples\windows\debug\framestrack\FramesTrackDemoMain.pas:

. Вы должны скомпилировать с полной информацией отладки в опциях Compiler и Linker в опциях вашего проекта delphi, чтобы это работало.

Обратите внимание, что вам не нужно вызывать LogException, он вызывается автоматически при добавлении обратного вызова уведомителя об исключении (JclAddExceptNotifier).не забудьте также вызвать JclRemoveExceptNotifier, когда форма или модуль данных, из которого вы добавляете его, уничтожается, как показано здесь:

procedure TForm1.LogException(ExceptObj: TObject; ExceptAddr: Pointer; IsOS: Boolean);
var
  TmpS: string;
  ModInfo: TJclLocationInfo;
  I: Integer;
  ExceptionHandled: Boolean;
  HandlerLocation: Pointer;
  ExceptFrame: TJclExceptFrame;

begin
  TmpS := 'Exception ' + ExceptObj.ClassName;
  if ExceptObj is Exception then
    TmpS := TmpS + ': ' + Exception(ExceptObj).Message;
  if IsOS then
    TmpS := TmpS + ' (OS Exception)';
  mmLog.Lines.Add(TmpS);
  ModInfo := GetLocationInfo(ExceptAddr);
  mmLog.Lines.Add(Format(
    '  Exception occured at $%p (Module "%s", Procedure "%s", Unit "%s", Line %d)',
    [ModInfo.Address,
     ModInfo.UnitName,
     ModInfo.ProcedureName,
     ModInfo.SourceName,
     ModInfo.LineNumber]));
  if stExceptFrame in JclStackTrackingOptions then
  begin
    mmLog.Lines.Add('  Except frame-dump:');
    I := 0;
    ExceptionHandled := False;
    while (chkShowAllFrames.Checked or not ExceptionHandled) and
      (I < JclLastExceptFrameList.Count) do
    begin
      ExceptFrame := JclLastExceptFrameList.Items[I];
      ExceptionHandled := ExceptFrame.HandlerInfo(ExceptObj, HandlerLocation);
      if (ExceptFrame.FrameKind = efkFinally) or
          (ExceptFrame.FrameKind = efkUnknown) or
          not ExceptionHandled then
        HandlerLocation := ExceptFrame.CodeLocation;
      ModInfo := GetLocationInfo(HandlerLocation);
      TmpS := Format(
        '    Frame at $%p (type: %s',
        [ExceptFrame.ExcFrame,
         GetEnumName(TypeInfo(TExceptFrameKind), Ord(ExceptFrame.FrameKind))]);
      if ExceptionHandled then
        TmpS := TmpS + ', handles exception)'
      else
        TmpS := TmpS + ')';
      mmLog.Lines.Add(TmpS);
      if ExceptionHandled then
        mmLog.Lines.Add(Format(
          '      Handler at $%p',
          [HandlerLocation]))
      else
        mmLog.Lines.Add(Format(
          '      Code at $%p',
          [HandlerLocation]));
      mmLog.Lines.Add(Format(
        '      Module "%s", Procedure "%s", Unit "%s", Line %d',
        [ModInfo.UnitName,
         ModInfo.ProcedureName,
         ModInfo.SourceName,
         ModInfo.LineNumber]));
      Inc(I);
    end;
  end;
  mmLog.Lines.Add('');
end;


procedure TForm1.FormCreate(Sender: TObject);
begin
  JclAddExceptNotifier(Form1.LogException);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  JclRemoveExceptNotifier(Form1.LogException);
end;

Это обычный код инициализации:

initialization

  JclStackTrackingOptions := JclStackTrackingOptions + [stExceptFrame];
  JclStartExceptionTracking;

Вот демонстрационная версия JCL FramesTrackExample.dproj:

enter image description here

В ваших целях измените код, добавляющий строку в TMemo.Lines, для записи в файл журнала на диске.вместо.Если у вас уже есть система ведения журналов, это здорово, а если нет, то рассмотрите Log4D .

0 голосов
/ 19 декабря 2011

Каждый новый вызов веб-службы - это новая тема.Некоторые ресурсы могут быть выделены предыдущим потоком, когда приходит следующий вызов службы и новый поток пытается получить к ним доступ.Или некоторые ресурсы могут быть освобождены одним потоком, когда другой поток пытается их использовать.Вы должны использовать TCriticalSection, чтобы убедиться, что все ресурсы доступны только для одного потока.Также убедитесь, что TCriticalSection является глобальной переменной и доступна для всех экземпляров.

...