Большое количество ошибок программных страниц при назначении TJpegImage TBitmap - PullRequest
2 голосов
/ 21 марта 2010

У меня есть приложение Delphi 6 Pro, которое обрабатывает входящие jpeg-кадры с сервера потокового видео.Код работает, но недавно я заметил, что со временем он генерирует огромное количество ошибок программных страниц.После некоторого исследования ошибки страницы появляются из-за одной конкретной графической операции.Обратите внимание, что несжатые растровые изображения имеют размер 320 x 240 или около 300 КБ, поэтому это не связано с обработкой больших изображений.Количество сгенерированных ошибок страниц недопустимо.В течение часа он может легко превысить 1000000 страниц.

Я создал урезанный тестовый пример, который выполняет код, который я включил ниже, по таймеру, 10 раз в секунду.Ошибки страницы появляются, когда я пытаюсь назначить TJpegImage TBitmap в методе GetBitmap ().Я знаю это, потому что я закомментировал эту строку и ошибки страницы не происходят.Метод assign () запускает операцию распаковки со стороны TJpegImage, когда он помещает распакованные биты во вновь созданное растровое изображение, которое возвращает GetBitmap ().Когда я запускаю утилиту pfmon от Microsoft (монитор ошибок страниц), я получаю огромное количество строк ошибок программных ошибок страниц, связанных с RtlFillMemoryUlong, так что это происходит во время операции заполнения буфера памяти.Сводная часть отчета pfmon, в которой показано, какая DLL вызвала ошибку страницы, не отображает имена DLL в крайнем левом столбце.Я пробовал это в другой системе, и там тоже происходит.

Может кто-нибудь предложить исправление или обходной путь?Вот кодОбратите внимание, что IReceiveBufferForClientSocket - это простой объект класса, который содержит байты в накопительном буфере.

function GetBitmap(theJpegImage: TJpegImage): Graphics.TBitmap;
begin
    Result := TBitmap.Create;

    Result.Assign(theJpegImage);
end;

// ---------------------------------------------------------------

procedure processJpegFrame(intfReceiveBuffer: IReceiveBufferForClientSocket);
var
    theBitmap: TBitmap;
    theJpegStream, theBitmapStream: TMemoryStream;
    theJpegImage: TJpegImage;
begin

    theBitmap := nil;
    theJpegImage := TJPEGImage.Create;
    theJpegStream:= TMemoryStream.Create;
    theBitmapStream := TMemoryStream.Create;

    try // 2
        // ************************ BEGIN JPEG FRAME PROCESSING

        // Load the JPEG image from the receive buffer.
        theJpegStream.Size := intfReceiveBuffer.numBytesInBuffer;
        Move(intfReceiveBuffer.bufPtr^, theJpegStream.Memory^, intfReceiveBuffer.numBytesInBuffer);

        theJpegImage.LoadFromStream(theJpegStream);

        // Convert to bitmap.
        theBitmap := GetBitmap(theJpegImage);

    finally
        // Free memory objects.
        if Assigned(theBitmap) then
            theBitmap.Free;
        if Assigned(theJpegImage) then
            theJpegImage.Free;
        if Assigned(theBitmapStream) then
            theBitmapStream.Free;
        if Assigned(theJpegStream) then
            theJpegStream.Free;
    end; // try()
end;

// ---------------------------------------------------------------

procedure TForm1.Timer1Timer(Sender: TObject);
begin
    processJpegFrame(FIntfReceiveBufferForClientSocket);
end;

// ---------------------------------------------------------------

procedure TForm1.FormCreate(Sender: TObject);
var
    S: string;
begin
    FIntfReceiveBufferForClientSocket := TReceiveBufferForClientSocket.Create(1000000);

    S := loadStringFromFile('c:\test.jpg');

    FIntfReceiveBufferForClientSocket.assign(S);
end;

// ---------------------------------------------------------------

Спасибо, Роберт

1 Ответ

0 голосов
/ 21 марта 2010

Похоже, что выделенные и свободные ресурсы не используются менеджером памяти.

Используйте fastmm или лучше, объедините их и утилизируйте их самостоятельно.

...