本文介绍了如何从已处理/捕获的异常中获取堆栈跟踪并将其转储到跟踪日志中的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们已经以Bob Swart的白皮书为指导,创建了一个Datasnap服务(使用Delphi XE)。它工作正常,我们已经将其部署到测试服务器。



现在,当我们执行大量请求(通过JMeter)时,出现了一个问题发生某种内存损坏。有些请求成功,有些则失败,并带有访问冲突。最后,它变得如此损坏,以至于对我们的OWN方法(不是DSAdmin方法)的每个请求都以访问冲突作为响应。



但是,由于无法在请求处理过程中捕获到异常,因此我无法获得更多信息。 b
$ b

如果我对该应用程序的VCL版本进行了大量测试,它仍然可以正常工作。



有没有人知道这可能是什么,或遇到相同的问题,或者您可以帮助我从捕获的异常中获取堆栈跟踪(在我的代码中,我无法编辑)?



谢谢

解决方案

要使用JEDI JCL记录捕获到的异常和未捕获到的异常,应安装。


We've created a Datasnap service (with Delphi XE), using Bob Swart's white paper as a guide. It works fine, and we've deployed it to our test server.

Now a problem occurs, when we have executed a large number of requests (through JMeter), some sort of memory corruption occurs. Some requests succeed, some fail with an access violation. In the end, it has become so corrupt, that every request to our OWN (not the DSAdmin) methods responds with an access violation.

However, I can't get my hands on a stacktrace to get more info, because the exception is already catched in the processing of the request.

If I test heavily with the VCL version of this application, it remains working correctly.

Has anyone any clue what this could be, or experienced the same problem, or can you help me get the stack trace from a caught exception (in someone else's code, which I can't edit)?

Thanks in advance.

解决方案

To log both caught and uncaught exceptions using JEDI JCL, you should install the JEDI JCL.

Then try some code like this code taken from jcl\examples\windows\debug\framestrack\FramesTrackDemoMain.pas:

You should compile with full Debug information on in both the Compiler and Linker options in your delphi project options, for this to work.

Note that you don't have to call LogException, it's called automatically one you've added the exception notifier callback (JclAddExceptNotifier). don't forget to also call JclRemoveExceptNotifier, when the form or data module you are adding it from is destroyed, as shown here:

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;

This is the usual initialization code:

initialization

  JclStackTrackingOptions := JclStackTrackingOptions + [stExceptFrame];
  JclStartExceptionTracking;

Here's the JCL FramesTrackExample.dproj demo running:

For your purposes, change the code that adds a line to TMemo.Lines, to write to a log file on disk instead. If you already have a logging system, that's great, and if not, then consider Log4D.

这篇关于如何从已处理/捕获的异常中获取堆栈跟踪并将其转储到跟踪日志中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

08-12 01:17