• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1608
  • Last Modified:

Access Violation Exception

Delphi-Experts,

I have written a program to display JPG-pictures using Delphi 3. For displaying the pictures I use components I haven't written myself.

When reading some bad JPG-pictures (maybe 1 in a 100) I get an access violation:

access violation at 0x232835: read of address 0xfff4b134
83 3A 00 74 63 E8 39 10 00 00 64 8B

I'll include a piece of two sources:
1) TMultip.pas : calls the function 'jpgfile';
2) DLL95V1.pas : calls the function 'readjpgfile'.

Source: TMultip.pas

uses
{$IFDEF DEL32}
  Windows,
{$ELSE}
  WinTypes,
  WinProcs,
{$ENDIF}
  DLL95V1, SysUtils, Messages, Classes, Graphics,
  Forms, Controls, Extctrls, StdCtrls, Menus, Mask,
  Buttons, Printers, Setsr31, Setcr31;


type
  published
    property ImageName  : String read GetMultiBitmap write WriteMultiName;

function TPMultiImage.GetMultiBitmap :  String;
var    Bitmap     : TBitmap;
       Pextension : String[4];
       OnExcept   : Boolean;
       Dith       : Integer;
       ReadRes    : Integer;

begin


 if Pextension = '.JPG' then begin
    try
     FreeMsg;
     Bitmap := TBitmap.Create;
     if not jpgfile(FFilename, ReadRes, Dith, Bitmap, TPMultiImageCallBack) then
       ErrorMessage('Reading jpg file failed');
    except
     Picture.Graphic := nil;
     Bitmap.Free;
     OnExcept:=True;
    end;
     if OnExcept then Goto BreakIt;
     Picture.Graphic:=Bitmap;
     Bitmap.Free;
     GetInfoAndType(FFilename);
 end;


end;


Source: DLL95V1.pas

const
  ImageLibDLL = 'SKY32V3C.DLL';

{Interface call}
Function jpgfile(Filename          : String;
                 Resolution        : Integer;
                 Dither            : Integer;
            var  Bitmap            : TBitmap;
           CallBackFunction        : TCallBackFunction) : Boolean;

var
 Fn   : Array[0..255] of Char;
 HPAL : HPalette;
 hBMP : HBitmap;
 Res  : SmallInt;
begin
  hPal:=GlobalPalette;
  StrPCopy(Fn, Filename);
  Res:=readjpgfile(Fn,
                   SmallInt(Resolution),
                   1, {size, 1= 1/1}
                   SmallInt(Dither),
                   hBMP,
                   HPAL,
                   CallBackFunction,
                   ShowErrorInDll);

 Bitmap.Handle := hBMP;
 Bitmap.Palette := HPAL;

 If Res < 1 then begin
   DllErrorProc(Res);
   Result:=False
 end else
   Result:=True;
  {$IFDEF ILTRIAL}
   Validate;
  {$ENDIF}
end;

Function readjpgfile; external ImageLibDLL index INDEX_READJPGFILE;

My actual question is how can I catch the 'access violation' and give a decent message instead of the application closing down.

Regards,
Gandalf the Grey.
0
detempel
Asked:
detempel
1 Solution
 
sfockCommented:
can you tell us, where exactly the Exception occures?
I can only guess that. it might be easier if you'd tell use where it is raised.

until then i can't say much except of
  except
    Picture.Graphic := nil;
    Bitmap.Free;
    OnExcept:=True;
   end;
   if OnExcept then Goto BreakIt;
lokks like pretty bad style .. but anyhow i can't encoubter a mistake within ...
0
 
detempelAuthor Commented:
I have traced the exception to:

   if not jpgfile(FFilename, ReadRes, Dith, Bitmap, TPMultiImageCallBack) then
      ErrorMessage('Reading jpg file failed');

I have put messages before and after this statement. The message before the statement is shown and immediately after that I get the 'access violation'. So it seems the try .. except construct doesn't catch the access violation. I think it is in the function 'jpgfile' somewhere.

I'm not very experience with catching exceptions. Apparently the 'access violation' exception can't be catched by the try .. except construct?
0
 
sfockCommented:
I am still not sure what is happening at the callbackfunction? Anyhow i guess that is not the problem.
But what is happing at the jumppoint "BreakIt"

I'd guess that any exception occures it is catched by the except block and something within this "BreakIt" makes the access violation ...

show me the BreakIt please
0
Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
detempelAuthor Commented:
BreakIt is a declared as a label and that label is at the end of the function TPMultiImage.GetMultiBitmap (using labels and jumps is indeed bad practice).

 if Pextension = '.JPG' then begin
    try
     FreeMsg;
     Bitmap := TBitmap.Create;
     if not jpgfile(FFilename, ReadRes, Dith, Bitmap, TPMultiImageCallBack) then
       ErrorMessage('Reading jpg file failed');
    except
     Picture.Graphic := nil;
     Bitmap.Free;
     OnExcept:=True;
    end;
     if OnExcept then Goto BreakIt;
     Picture.Graphic:=Bitmap;
     Bitmap.Free;
     GetInfoAndType(FFilename);
 end;

 BreakIt:
 Temps:=UpperCase(FFilename);
 result:=Temps;
end;

Temps and FFilename are of type TFilename. FFilename is part of the type TPMultiImage.

I have put extra messages between the code but when I load the faulty jpg-picture I only get the access violation. I have put the first message at the beginning of the function TPMultiImage.GetMultiBitmap.

I have tried extra messages before with another faulty jpg-picture. In that case the last message that showed was the message before the check on 'jpgfile'. I'm sure I used the same procedure 'ErrorMessage' to display the debug-information.
0
 
sfockCommented:
hmm it does not look like if the BreakIt code would be the problem ...
Are you debugging in the IDE?? if the option is set it does alway show any exception also if it was catched and not be shown to the user ...

but if this is not your problem then place a message here :
  except
    ShowMessage('onExceptIN');
    Picture.Graphic := nil;
    ShowMessage('onExcept1');
    Bitmap.Free;
    ShowMessage('onExcept2');
    OnExcept:=True;
    ShowMessage('onExceptOUT');
   end;
at least 'onExceptIN' should appear ...
0
 
detempelAuthor Commented:
I have altered the code this way:

    if not jpgfile(FFilename, ReadRes, Dith, Bitmap, TPMultiImageCallBack) then
       ErrorMessage('Reading jpg file failed');
    except
     { ErrorMessage('Aan het begin van het except-block'); }
     ShowMessage('onExceptIN');
     Picture.Graphic := nil;
     { ErrorMessage('Vrijgeven Graphic'); }
     ShowMessage('onExcept1');
     Bitmap.Free;
     { ErrorMessage('Vrijgeven Bitmap'); }
     ShowMessage('onExcept2');
     OnExcept:=True;
     { ErrorMessage('Aan het einde van het except-block') }
     ShowMessage('onExceptOUT')
    end;
     if OnExcept then Goto BreakIt;

Testing from within the IDE doesn't display the message 'onExceptIN'.

The code is part of a package. After I change the code I recompile the package. And then I recompile my program with the altered package (I'm not sure but I think that a showmessage in a package doesn't work).
0
 
sfockCommented:
>showmessage in a package doesn't work
why shouldn't it?

anyhow let me carry the informations together:

An Access violation occures within the function jpgfile

the call of this function is withion a try except block

but the except block is nerver entered

is that correct?

This should not be possible. The only way i have ever seen a similar behavior is if an exception occures within a except or finally block.

i can't see such a mistake here. It might happen at readjpgfile() or the CallBackFunction.

maybe we should take a look in there ... except of that i have no other ideas just a desperate trial:

change the except block as follows:

  except
    on e : exception do begin
      // you can also use your ErrorMessage instead of showMessage
      showMessage('Ex:'+e.ClassName+' msg: '+e.message);
      Picture.Graphic := nil;
      Bitmap.Free;
      OnExcept:=True;
    end;
   end;
0
 
detempelAuthor Commented:
I have discovered with this JPG-picture the access violation apparently occurs at another place. I have traced it to this piece of code:

  StrPCopy(Fn, Filename);
  ShowMessage('Na StrPCopy');
  try
    Res:=fileinfo(Fn,
                  @Ft,
                  BFwidth,
                  BFHeight,
                  BFbitspixel,
                  BFplanes,
                  BFnumcolors,
                  @Fc,
                  ShowErrorInDll);
  except
    ShowMessage('Oops')
  end;

The try-part triggers the access violation but I get no message 'Oops'. I do get the message 'Na StrPCopy'.

The function 'fileinfo' is declared as follows:

Function fileinfo; external ImageLibDLL index INDEX_FILEINFO;
0
 
sfockCommented:
well, i am really sorry, i have no further idea.
There are severeal reasons why a AcVio could appear, when calling a DLL function, but anyhow it has to be catched by this except block!!!

if not i won't know a reason. The only thing i can imagine is that your debugging results are not correct ...
If you'd place another message behind the try...except block would it appear?

StrPCopy(Fn, Filename);
 ShowMessage('Na StrPCopy');
 try
   Res:=fileinfo(Fn,
                 @Ft,
                 BFwidth,
                 BFHeight,
                 BFbitspixel,
                 BFplanes,
                 BFnumcolors,
                 @Fc,
                 ShowErrorInDll);
 except
   ShowMessage('Oops')
 end;
 ShowMessage('FileInfo done')

0
 
pderuiterCommented:
What's that "showErrorInDll"? the way an access violation will escape from your try except is if it is "handled" by another try except.
0
 
sfockCommented:
pderuiter
but it would not appear then...
0
 
detempelAuthor Commented:
const
 ShowErrorInDll    = 0; {1 is show messagebox in dll 0 is in this unit}

I have tried changing ShowErrorInDll to 1 but that didn't change a thing. Since 'FileInfo' is a black box to me I don't know what else to do.

Here's the definition of the function call:

{DLL call}
Function   fileinfo(Filename       : PChar;
                    FileType       : PChar;
                var Fwidth         : SmallInt;
                var FHeight        : SmallInt;
                var Fbitspixel     : SmallInt;
                var Fplanes        : SmallInt;
                var Fnumcolors     : SmallInt;
                    Fcompression   : PChar;
                   ShowDllErrorMsg : SmallInt) : SmallInt; {$IFDEF DEL32}
                                                           StdCall;
                                                         {$ELSE}
                                                           Far;
                                                         {$ENDIF}

When I try to read the picture using 'IrfanView' I get the error 'Bogus Huffman table definition'.

Since ShowErrorInDll has the value zero I would expect the error to be catched by the try ... except construct.
0
 
detempelAuthor Commented:
I have taken another approach. I have tested using the JPEG-demo in the directory help/examples/jpeg:

procedure TForm1.OpenFile(const Filename: string);
begin
  try
    Image1.Picture.LoadFromFile(Filename);
  except
    on EInvalidGraphic do
      Image1.Picture.Graphic := nil;
    else ShowMessage('Oops')
  end;
  SetJPEGOptions(self);
end;

I get an error message 'Project JPEGPROJ.exe raised exception class EJPEG with message 'JPEG error #30'. Process stopped. Use Step or Run to continue.'. When I press Run the program continues without showing the message 'Oops'.

So in this case the except-block is also not entered and this is an example from Borland.
0
 
joinedCommented:
You can try EurekaLog (www.eurekalog.com).

EurekaLog is an add-in tool that gives to your application (GUI, Console, Web, etc.) the ability to catch every exception, and generates a detailed log of call stack (with unit, class, method and line #), showing and sending it back to you via email.

--
Best regards...

Fabio Dell'Aria.
0
 
serg1233Commented:
May be THE PROBLEM in  "StrPCopy" - it doesnt work correctly if it have "0"...
it looking for "0" like the end of the string...:-)

All the Best
0
 
detempelAuthor Commented:
I have closed this question by awarding the points to the first one helping me out. I have found a work around where I can catch the error-message and thus prevent the 'access violation' from occuring.

Regards,
Gandalf the Grey.
0

Featured Post

Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Tackle projects and never again get stuck behind a technical roadblock.
Join Now