У меня есть собственный фильтр push-кода, написанный на Delphi 6 с использованием библиотеки компонентов DSPACK DirectShow на компьютере с Windows XP / 32.Во время кодирования я столкнулся с проблемой с ошибками проверки диапазона , возникающими в модуле BaseClass , принадлежащем DSPACK (BaseClass.pas), после того как я включил Проверка диапазона вОпции компилятора моего приложения.
Ошибка происходит во время моего метода EnumPins ().Обратите внимание, что этот метод находится в модуле BaseClass DSPACK, а не в моем приложении.Я отследил проблему и обнаружил, что она возникает, когда построенный мной график фильтра, использующий мой фильтр, воспроизводит фильтр.Обратите внимание, что мой фильтр напрямую включен в мое приложение как частный незарегистрированный фильтр, а не как внешний AX.Когда DirectShow вызывает метод базового класса TBCEnumPins.Next () , если параметр ppPins равен NIL , возникает ошибка проверки диапазона.Поскольку я не являюсь экспертом по DirectShow, я не уверен, как правильно исправить эту ошибку, не нарушая при этом процесс перечисления выводов DirectShow.Если вместо этого это истинное условие ошибки, которое не следует игнорировать, то мне нужно знать, что является правильным кодом исключения или HRESULT для возврата в этом событии.Может кто-нибудь сказать мне, как правильно настроить этот код для параметра NIL ppPins?Полный код метода ниже со строкой, в которой происходит ошибка проверки диапазона, выделен:
function TBCEnumPins.Next(cPins: ULONG; out ppPins: IPin; pcFetched: PULONG): HRESULT;
type
TPointerDynArray = array of Pointer;
TIPinDynArray = array of IPin;
var
Fetched: cardinal;
RealPins: integer;
Pin: TBCBasePin;
begin
// ATI: Debugging range check error.
try
if pcFetched <> nil then
pcFetched^ := 0
else
if (cPins>1) then
begin
result := E_INVALIDARG;
exit;
end;
Fetched := 0; // increment as we get each one.
// Check we are still in sync with the filter
// If we are out of sync, we should refresh the enumerator.
// This will reset the position and update the other members, but
// will not clear cache of pins we have already returned.
if AreWeOutOfSync then
Refresh;
// Calculate the number of available pins
RealPins := min(FPinCount - FPosition, cPins);
if RealPins = 0 then
begin
result := S_FALSE;
exit;
end;
{ Return each pin interface NOTE GetPin returns CBasePin * not addrefed
so we must QI for the IPin (which increments its reference count)
If while we are retrieving a pin from the filter an error occurs we
assume that our internal state is stale with respect to the filter
(for example someone has deleted a pin) so we
return VFW_E_ENUM_OUT_OF_SYNC }
while RealPins > 0 do
begin
// Get the next pin object from the filter */
inc(FPosition);
Pin := FFilter.GetPin(FPosition-1);
if Pin = nil then
begin
// If this happend, and it's not the first time through, then we've got a problem,
// since we should really go back and release the iPins, which we have previously
// AddRef'ed.
ASSERT(Fetched = 0);
result := VFW_E_ENUM_OUT_OF_SYNC;
exit;
end;
// We only want to return this pin, if it is not in our cache
if FPinCache.IndexOf(Pin) = -1 then
begin
// From the object get an IPin interface
TPointerDynArray(@ppPins)[Fetched] := nil; // <<<<<< THIS IS WHERE THE RANGE CHECK ERROR OCCURS.
TIPinDynArray(@ppPins)[Fetched] := Pin;
inc(Fetched);
FPinCache.Add(Pin);
dec(RealPins);
end;
end; // while RealPins > 0 do
if (pcFetched <> nil) then pcFetched^ := Fetched;
if (cPins = Fetched) then result := NOERROR else result := S_FALSE;
except
On E: Exception do
begin
OutputDebugString(PChar(
'(TBCEnumPins.Next) Exception class name(' + E.ClassName + ') message: ' + E.Message
));
raise;
end;
end;
end;
ОБНОВЛЕНИЕ: Похоже, что код DSPACK является звуковым с технической точки зрения, нонемного странно с точки зрения идиомы кодирования и структурировано таким образом, что не совместимо с проверкой диапазона.NIL, поступающий через параметр «out» ppPins, отображается в буфер назначения, который вызывающая сторона передает TBCEnumPins.Next () в качестве параметра ppPins.Например, приведенный ниже код взят с этой страницы:
http://tanvon.wordpress.com/2008/09/07/enumerating-the-directshow-filter-pin/
На этой странице приведен следующий код, который взаимодействует с фильтром DirectShow для перечисления выводов фильтра:
IEnumPins * pEP;
pSF->EnumPins(&pEP);
IPin * pOutPin;
while(pEP->Next(1,&pOutPin,0) == S_OK)
{
PIN_DIRECTION pDir;
pOutPin->QueryDirection(&pDir);
if(pDir == PINDIR_OUTPUT)
break;// success
pOutPin->Release();
}
pEP->Release();
Сообщая методу Next (), сколько выводов нужно извлечь, код метода TBCEnumPins.Next () с его необычным приведением динамического массива оказывается безопасным, поскольку он копирует в параметр ppPins "out" только столько, сколькокак булавки, как было запрошено в параметре "cPins" функций Next ().Пока вызывающая сторона передает целевой буфер, который может содержать количество пинов, запрошенных в «cPins», все работает нормально (до тех пор, пока проверка диапазона отключена).Обратите внимание, что в этом случае переменная IPin с именем «outPin» является целевым буфером.Ошибка проверки диапазона возникает, если проверка диапазона включена, поскольку Delphi рассматривает NIL как массив нулевой длины.