2

クラス、TBaseDBと呼ばれる基本クラスを使用するアプリがあり、TBaseDBの子孫が多数あり、すべてDIRECTの兄弟であり、そのうちの1つであるTOraDBのみが開始されていますが、後でTSQLDBなどが追加されます。

私のアプリはクラスの1つのインスタンスを使用し、それはグローバルインスタンス、つまりPROJと呼ばれるグローバル変数です。コンストラクター、デストラクタ、およびグローバル変数の理解に問題があり、アプリの他の場所でEStackOverflowが発生しています。PROJ.CREATEをコメントアウトすると、EStackOverflowはなくなります。

私のコンストラクターは変数を設定するだけで、リンクリスト、Aray、またはその他のメモリを大量に消費するオブジェクトを動的に作成しません。

ここにいくつかのコードスニペットがあります。

// global var definition
// Specifically of BASE class, so I can call any child class without knowing which child class it is...
PROJ : TBaseDB;

私のエラーを引き起こす私のルーチン...

procedure TForm1.ShowBug;
begin
  // We have clicked on 'Create New Oracle Project

  // Now create our PROJ object.
  // This is defined globally, but MAY have been used before
  // so 'zero' it out
 FreeAndNil(PROJ);
 // Note that the create is on the CHILD class, not the BASE class
 // If I DON'T create the class, no error.... 
 PROJ := TOraDB.Create;

 // ... other code
end;

これが私のクラス定義です。

Type
  TBaseDB = class
  published    
  public

    DAC_ID: Integer;
    DAC_ShortName : String;
    DAC_LongName: String;

    Constructor Create;
    Destructor Destroy; override;
    ... other stuff
  end;

implementation


// TBaseDB /////////////////////////////////////////////////////////////////
constructor TBaseDB.Create;
begin
  inherited;
end;

destructor TBaseDB.Destroy;
begin
 // If I comment out next two lines, my issue goes away
 // but shouldn't I have them....?  
  Self.Free;
  Self := nil;

  // Always call the parent destructor after running your own code
  inherited;
end;

これがTOraDBクラスの私の定義です

Type
  TOraDB = Class(TBaseDB)
  public
    Constructor Create;
    Destructor Destroy; override;
   ... other stuff
  End;

implementation

// ------------------------------------------------------------------------------
constructor TOraDB.Create;
begin
  inherited;

  // Now set up the information about the source database.  We know it is Oracle
  // even though we DONT know if it is connected
  DAC_ID := 4;
  DAC_ShortName := 'Ora';
  DAC_LongName := 'Oracle';
end;

// -----------------------------------------------------------------------------
destructor TOraDB.Destroy;
begin
  // Always call the parent destructor after running your own code
  inherited;
end;

グローバルクラス変数の「リセット」について何か理解していません。どこでリセットすればよいので、引き続きGLOBAL変数PROJを使用できますか?

ありがとう、

GS

4

2 に答える 2

12

Self.Freeクラスのデストラクタを呼び出さないでください。

無料通話DestroyとDestroy通話無料......StackOverflowまで

destructor TBaseDB.Destroy;
begin

  // Don't do that at all in a destructor

  // Self.Free;
  // Self := nil;

  // Always call the parent destructor after running your own code
  inherited;
end;

TObject.Freeインスタンスがnilでないかどうかをテストするため、デストラクタの安全な呼び出しです。

procedure TObject.Free;
begin
  if Self <> nil then
    Destroy;
end;

編集

グローバル変数に関してPROJは、単純な(しかしあまり賢明ではない)解決策があります

destructor TBaseDB.Destroy;
begin

  if Self = PROJ then
    PROJ := nil;

  // Always call the parent destructor after running your own code
  inherited;
end;

代わりに、シングルトンの実装を確認する必要があります。

于 2013-03-05T12:51:52.890 に答える
2

使用しないでください:

  Self.Free;
  Self := nil;

あなたのデストラクタで。

于 2013-03-05T12:52:28.693 に答える