4

Bob Swart のホワイト ペーパーをガイドとして使用して、Datasnap サービス (Delphi XE を使用) を作成しました。正常に動作し、テスト サーバーにデプロイしました。

ここで問題が発生します。(JMeter を介して) 多数のリクエストを実行すると、何らかのメモリ破損が発生します。成功するリクエストもあれば、アクセス違反で失敗するリクエストもあります。最終的に、非常に壊れてしまい、(DSAdmin ではなく) OWN メソッドへのすべての要求がアクセス違反で応答するようになりました。

ただし、リクエストの処理で例外が既にキャッチされているため、スタックトレースを取得して詳細情報を取得することはできません。

このアプリケーションの VCL バージョンで頻繁にテストすると、正常に動作し続けます。

これが何であるか、または同じ問題を経験した人はいますか、またはキャッチされた例外からスタックトレースを取得するのを手伝ってもらえますか(編集できない他の人のコードで)?

前もって感謝します。

4

2 に答える 2

7

JEDI JCL を使用してキャッチされた例外とキャッチされなかった例外の両方をログに記録するには、JEDI JCLをインストールする必要があります。

次に、から取得した次のコードのようなコードを試してくださいjcl\examples\windows\debug\framestrack\FramesTrackDemoMain.pas

これを機能させるには、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 デモを次に示します。

ここに画像の説明を入力

目的に合わせて、TMemo.Lines に行を追加するコードを変更し、代わりにディスク上のログ ファイルに書き込むようにします。すでにロギング システムがある場合は、それで十分です。そうでない場合は、Log4Dを検討してください。

于 2011-12-16T21:23:01.707 に答える
-1

すべての新しい Web サービス呼び出しは新しいスレッドです。次のサービス呼び出しが来て、新しいスレッドがそれらにアクセスしようとすると、前のスレッドによっていくつかのリソースが割り当てられる可能性があります。または、別のスレッドがそれらを使用しようとすると、あるスレッドによって一部のリソースが解放される場合があります。TCriticalSection を使用して、すべてのリソースが 1 つのスレッドだけで使用できるようにする必要があります。また、TCriticalSection がグローバル変数であり、すべてのインスタンスからアクセスできることを確認してください。

于 2011-12-19T19:49:51.253 に答える