3

AVIファイルの継続時間を取得する方法を示すサンプルを含むStackOverflowの投稿を見つけました。

AVIファイルの継続時間を取得する

Delphi 6アプリで目的に合わせて変更し、以下のコードを作成しました。最初に、AviFileExit()を呼び出す前に、IAviFileポインターを無効にする行を削除しました。しかし、それを行ったときに、AviFileExit()が呼び出されたときにアクセス違反が発生しました。回線を復元すると、アクセス違反はなくなりました。

AviFileExit()を呼び出す前にIAviFile参照を削除する必要があるのはなぜですか?これはメモリリークですか?ここでは、通常のインターフェイス参照カウントが適切に機能すると思いますが、明らかに機能しません。AviStreamRelease()などを呼び出すなどのエラーを排除する別の方法はありますか?

これが私のコードです:

function getAviDurationSecs(theAviFilename: string): Extended;
var
    aviFileInfo : TAVIFILEINFOW;
    intfAviFile : IAVIFILE;
    framesPerSecond : Extended;
begin
    intfAviFile := nil;

    AVIFileInit;

    try
        // Open the AVI file.
        if AVIFileOpen(intfAviFile, PChar(theAviFilename), OF_READ, nil) <> AVIERR_OK then
            raise Exception.Create('(getAviDurationSecs) Error opening the AVI file: ' + theAviFilename);

        try
            // Get the AVI file information.
            if AVIFileInfoW(intfAviFile, aviFileInfo, sizeof(aviFileInfo))  <> AVIERR_OK then
                raise Exception.Create('(getAviDurationSecs) Unable to get file information record from the AVI file: ' + theAviFilename);

            // Zero divide protection.
            if aviFileInfo.dwScale < 1 then
                raise Exception.Create('(getAviDurationSecs) Invalid dwScale value found in the AVI file information record: ' + theAviFilename);

            // Calculate the frames per second.
            framesPerSecond := aviFileInfo.dwRate / aviFileInfo.dwScale;

            Result := aviFileInfo.dwLength  / framesPerSecond;
        finally
            AVIFileRelease(intfAviFile);
            // Commenting out the line below that nukes the IAviFile
            //  interface reference leads to an access violation when
            //  AVIFileExit() is called.
            Pointer(intfAviFile) := nil;
        end;
    finally
        AVIFileExit;
    end;
end;
4

1 に答える 1

5

AVIFileRelease()Delphiはインターフェイスを解放した ことを認識していないため、変数を手動でクリアする必要があります。AVIFileRelease()は変数をに設定しないnilため、変数にはnil以外の値が含まれます。手動でクリアしないと、DelphiはRelease()、変数がスコープ外になったとき(呼び出し)に変数を呼び出そうとしてAVIFileExit()クラッシュします。

IAVIFileインターフェイスは子孫であるため、 Microsoftが最初に関数をIUknown作成した理由はわかりません。AVIFileRelease()インターフェイスの参照カウントをデクリメントし、カウントがゼロになった場合はクリーンアップを実行します。インターフェイスの背後にある実装は、明示的な関数を必要とせずに、それを内部的に処理するだけで済みます。だから、それはマイクロソフトの悪いことです。

于 2012-05-18T02:14:46.873 に答える