在调用AviFileExit()之前,为什么有必要在这种情况下核对IAviFile指针?

Rob*_*ler 3 delphi vfw avi access-violation

我发现了一个Stack Overflow帖子,其中有一个示例显示了如何获取AVI文件的持续时间:

获取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;
Run Code Online (Sandbox Code Playgroud)

Rem*_*eau 5

您必须手动清除变量,因为Delphi不知道AVIFileRelease()发布了该接口. AVIFileRelease()不会nil为您设置变量,因此变量仍然具有非零值.如果你不manally清除它,德尔福将尝试调用Release()该变量时,它超出范围(以后AVIFileExit()调用)和崩溃.

IAVIFile接口是一个IUknown后代,所以我不知道为什么微软创造了AVIFileRelease()摆在首位的功能.如果计数降至零,它会递减接口的引用计数并执行清理.接口背后的实现可以简单地在内部处理,而不需要显式函数.所以那是微软的坏事.