2012-05-18 6 views
3

나는 AVI 파일의 지속 시간을 얻을하는 방법을 보여주는 샘플 스택 오버플로 게시물을 발견 :AviFileExit()을 호출하기 전에이 경우 IAviFile 포인터를 핵으로 남겨 둘 필요가있는 이유는 무엇입니까?

Getting AVI file duration

내 델파이 6 응용 프로그램 내 목적을 수정하고 아래 코드를 만들었습니다. 처음에는 AviFileExit()을 호출하기 전에 IAviFile 포인터를 숨기는 선을 제거했습니다. 그러나 내가 그렇게했을 때 AviFileExit()가 호출 될 때 액세스 위반이 발생했습니다. 나는 회선을 복구했고 접근 위반은 사라졌다.

왜 AviFileExit()을 호출하기 전에 IAviFile 참조를 핵 생성해야합니까? 이것은 메모리 누출인가요? 나는 정상적인 인터페이스 참조 카운팅이 여기에서 제대로 작동한다고 생각하지만 분명히 그렇지 않다. AviStreamRelease() 등을 호출하는 것과 같은 오류를 제거하는 또 다른 방법이 있습니까? 당신은 델파이 AVIFileRelease() 인터페이스를 발표 것을 알고하지 않기 때문에 수동으로 변수를 취소해야

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; 

답변

5

:

여기 내 코드입니다. AVIFileRelease()은 변수를 nil으로 설정하지 않으므로 변수에 여전히 nil이 아닌 값이 있습니다. 수동으로 지우지 않으면 델파이는 범위를 벗어나 (AVIFileExit() 호 이후) 변수에 Release()을 호출하려고 시도하고 충돌합니다.

IAVIFile 인터페이스는 IUknown의 자손이므로 Microsoft가 처음에 AVIFileRelease() 함수를 만든 이유를 알 수 없습니다. 인터페이스의 참조 횟수를 감소시키고 카운트가 0으로 떨어지면 정리를 수행합니다. 인터페이스 뒤에있는 구현은 명시 적 기능을 필요로하지 않고 내부적으로 처리 할 수 ​​있습니다. 그래서 마이크로 소프트가 나쁘다.

+0

감사합니다. 적어도 지금 나는 왜 그런지 압니다. –