Recent

Author Topic: Access violation on Free  (Read 5243 times)

Leledumbo

  • Hero Member
  • *****
  • Posts: 8718
  • Programming + Glam Metal + Tae Kwon Do = Me
Access violation on Free
« on: August 28, 2010, 06:27:51 am »
NOTE: please download the attached source and compile (requires fpc version with TFPGObjectList in fgl unit)

I'd like to improve my compiler so that it could process incorrect source as well (no crash, no leaks). So I try removing one closing block symbol and raise an exception in some parsing routines. Here's a little look:
Code: [Select]
function TEMLParser.Parse: TEMLERD;
begin
  try
    Result := ParseERD;
  except
    on e: EEndOfFile do
      with FLexer.CurrentToken do
        FErrorList.Add(TParseError.Create(Line,Col,e.Message));
  end;
end;
...
function TEMLParser.ParseEntities: TEMLEntities;
begin
  Result := TEMLEntities.Create;

  Expected(tkEntities);
  Expected(tkOpenBlock);
  while not Accepted(tkCloseBlock) and not Accepted(tkEOF) do
    Result.AddEntity(ParseEntity);
  if FLexer.CurrentToken.Kind = tkEOF then
    raise EEndOfFile.Create;
end;
Here's how Parse gets called in the program:
Code: [Select]
Parser := TEMLParser.Create(TEMLLexer.Create(InputStream));
    with Parser do
      try
        AST := Parser.Parse;
        if Errors.Count > 0 then
          for i := 0 to Errors.Count - 1 do
            WriteLn(StdErr,{ParamStr(1) + ' ' + }TParseError(Errors[i]).Message)
        else begin
          try
            CodeLines := TStringList.Create;
            AST.GetCode(CodeLines);
            WriteLn(CodeLines.Text);
          finally
            CodeLines.Free;
          end;
        end;
        AST.Free;
      finally
        Parser.Free;
      end;
Compiled with -glh, I got access violation on Parser.Free, and many unfreed blocks.
Quote
(7,3): tkIdentifier expected, but tkRelationships(relationships) found
(10,3): tkOpenBlock expected, but tkCloseBlock(}) found
(10,3): tkIdentifier expected, but tkCloseBlock(}) found
(12,1): End of file encountered in the middle of parsing
Access violation
Heap dump by heaptrc unit
376 memory blocks allocated : 11706/13880
350 memory blocks freed     : 8037/10120
26 unfreed memory blocks : 3669
True heap size : 360448 (128 used in System startup)
True free heap : 354640
Should be : 354896
Call trace for block $0008E540 size 264
  $00424A56  TEMLPARSER__PARSEENTITY,  line 116 of emlparser.pas
  $00424930  TEMLPARSER__PARSEENTITIES,  line 100 of emlparser.pas
  $00424872  TEMLPARSER__PARSEERD,  line 86 of emlparser.pas
  $00425301  TEMLPARSER__PARSE,  line 238 of emlparser.pas
  $00401653  main,  line 25 of emlc.lpr
  $0040CDB1
Call trace for block $000601B0 size 20
  $004095B8
  $00424BAF  TEMLPARSER__PARSEFIELDS,  line 137 of emlparser.pas
  $00424A1B  TEMLPARSER__PARSEENTITY,  line 113 of emlparser.pas
  $00424930  TEMLPARSER__PARSEENTITIES,  line 100 of emlparser.pas
  $00424872  TEMLPARSER__PARSEERD,  line 86 of emlparser.pas
  $00425301  TEMLPARSER__PARSE,  line 238 of emlparser.pas
  $00401653  main,  line 25 of emlc.lpr
  $0040CDB1
Call trace for block $0008E3F0 size 261
  $00424B4E  TEMLPARSER__PARSEFIELD,  line 130 of emlparser.pas
  $00424BA5  TEMLPARSER__PARSEFIELDS,  line 137 of emlparser.pas
  $00424A1B  TEMLPARSER__PARSEENTITY,  line 113 of emlparser.pas
  $00424930  TEMLPARSER__PARSEENTITIES,  line 100 of emlparser.pas
  $00424872  TEMLPARSER__PARSEERD,  line 86 of emlparser.pas
  $00425301  TEMLPARSER__PARSE,  line 238 of emlparser.pas
  $00401653  main,  line 25 of emlc.lpr
  $0040CDB1
Call trace for block $0006D8D8 size 25
  $00424B9A  TEMLPARSER__PARSEFIELDS,  line 135 of emlparser.pas
  $00424A1B  TEMLPARSER__PARSEENTITY,  line 113 of emlparser.pas
  $00424930  TEMLPARSER__PARSEENTITIES,  line 100 of emlparser.pas
  $00424872  TEMLPARSER__PARSEERD,  line 86 of emlparser.pas
  $00425301  TEMLPARSER__PARSE,  line 238 of emlparser.pas
  $00401653  main,  line 25 of emlc.lpr
  $0040CDB1
Call trace for block $0008E2A0 size 264
  $00424A56  TEMLPARSER__PARSEENTITY,  line 116 of emlparser.pas
  $00424930  TEMLPARSER__PARSEENTITIES,  line 100 of emlparser.pas
  $00424872  TEMLPARSER__PARSEERD,  line 86 of emlparser.pas
  $00425301  TEMLPARSER__PARSE,  line 238 of emlparser.pas
  $00401653  main,  line 25 of emlc.lpr
  $0040CDB1
Call trace for block $0008E150 size 261
  $00424B4E  TEMLPARSER__PARSEFIELD,  line 130 of emlparser.pas
  $00424BBC  TEMLPARSER__PARSEFIELDS,  line 139 of emlparser.pas
  $00424A1B  TEMLPARSER__PARSEENTITY,  line 113 of emlparser.pas
  $00424930  TEMLPARSER__PARSEENTITIES,  line 100 of emlparser.pas
  $00424872  TEMLPARSER__PARSEERD,  line 86 of emlparser.pas
  $00425301  TEMLPARSER__PARSE,  line 238 of emlparser.pas
  $00401653  main,  line 25 of emlc.lpr
  $0040CDB1
Call trace for block $0005FEB0 size 20
  $004095B8
  $00424BAF  TEMLPARSER__PARSEFIELDS,  line 137 of emlparser.pas
  $00424A1B  TEMLPARSER__PARSEENTITY,  line 113 of emlparser.pas
  $00424930  TEMLPARSER__PARSEENTITIES,  line 100 of emlparser.pas
  $00424872  TEMLPARSER__PARSEERD,  line 86 of emlparser.pas
  $00425301  TEMLPARSER__PARSE,  line 238 of emlparser.pas
  $00401653  main,  line 25 of emlc.lpr
  $0040CDB1
Call trace for block $0008E000 size 261
  $00424B4E  TEMLPARSER__PARSEFIELD,  line 130 of emlparser.pas
  $00424BA5  TEMLPARSER__PARSEFIELDS,  line 137 of emlparser.pas
  $00424A1B  TEMLPARSER__PARSEENTITY,  line 113 of emlparser.pas
  $00424930  TEMLPARSER__PARSEENTITIES,  line 100 of emlparser.pas
  $00424872  TEMLPARSER__PARSEERD,  line 86 of emlparser.pas
  $00425301  TEMLPARSER__PARSE,  line 238 of emlparser.pas
  $00401653  main,  line 25 of emlc.lpr
  $0040CDB1
Call trace for block $0006D868 size 25
  $00424B9A  TEMLPARSER__PARSEFIELDS,  line 135 of emlparser.pas
  $00424A1B  TEMLPARSER__PARSEENTITY,  line 113 of emlparser.pas
  $00424930  TEMLPARSER__PARSEENTITIES,  line 100 of emlparser.pas
  $00424872  TEMLPARSER__PARSEERD,  line 86 of emlparser.pas
  $00425301  TEMLPARSER__PARSE,  line 238 of emlparser.pas
  $00401653  main,  line 25 of emlc.lpr
  $0040CDB1
Call trace for block $0008DEB0 size 264
  $00424A56  TEMLPARSER__PARSEENTITY,  line 116 of emlparser.pas
  $00424930  TEMLPARSER__PARSEENTITIES,  line 100 of emlparser.pas
  $00424872  TEMLPARSER__PARSEERD,  line 86 of emlparser.pas
  $00425301  TEMLPARSER__PARSE,  line 238 of emlparser.pas
  $00401653  main,  line 25 of emlc.lpr
  $0040CDB1
Call trace for block $0008DD60 size 261
  $00424B4E  TEMLPARSER__PARSEFIELD,  line 130 of emlparser.pas
  $00424BBC  TEMLPARSER__PARSEFIELDS,  line 139 of emlparser.pas
  $00424A1B  TEMLPARSER__PARSEENTITY,  line 113 of emlparser.pas
  $00424930  TEMLPARSER__PARSEENTITIES,  line 100 of emlparser.pas
  $00424872  TEMLPARSER__PARSEERD,  line 86 of emlparser.pas
  $00425301  TEMLPARSER__PARSE,  line 238 of emlparser.pas
  $00401653  main,  line 25 of emlc.lpr
  $0040CDB1
Call trace for block $0008DC10 size 261
  $00424B4E  TEMLPARSER__PARSEFIELD,  line 130 of emlparser.pas
  $00424BBC  TEMLPARSER__PARSEFIELDS,  line 139 of emlparser.pas
  $00424A1B  TEMLPARSER__PARSEENTITY,  line 113 of emlparser.pas
  $00424930  TEMLPARSER__PARSEENTITIES,  line 100 of emlparser.pas
  $00424872  TEMLPARSER__PARSEERD,  line 86 of emlparser.pas
  $00425301  TEMLPARSER__PARSE,  line 238 of emlparser.pas
  $00401653  main,  line 25 of emlc.lpr
  $0040CDB1
Call trace for block $0005F790 size 20
  $004095B8
  $00424BAF  TEMLPARSER__PARSEFIELDS,  line 137 of emlparser.pas
  $00424A1B  TEMLPARSER__PARSEENTITY,  line 113 of emlparser.pas
  $00424930  TEMLPARSER__PARSEENTITIES,  line 100 of emlparser.pas
  $00424872  TEMLPARSER__PARSEERD,  line 86 of emlparser.pas
  $00425301  TEMLPARSER__PARSE,  line 238 of emlparser.pas
  $00401653  main,  line 25 of emlc.lpr
  $0040CDB1
Call trace for block $0008DAC0 size 261
  $00424B4E  TEMLPARSER__PARSEFIELD,  line 130 of emlparser.pas
  $00424BA5  TEMLPARSER__PARSEFIELDS,  line 137 of emlparser.pas
  $00424A1B  TEMLPARSER__PARSEENTITY,  line 113 of emlparser.pas
  $00424930  TEMLPARSER__PARSEENTITIES,  line 100 of emlparser.pas
  $00424872  TEMLPARSER__PARSEERD,  line 86 of emlparser.pas
  $00425301  TEMLPARSER__PARSE,  line 238 of emlparser.pas
  $00401653  main,  line 25 of emlc.lpr
  $0040CDB1
Call trace for block $0006D7F8 size 25
  $00424B9A  TEMLPARSER__PARSEFIELDS,  line 135 of emlparser.pas
  $00424A1B  TEMLPARSER__PARSEENTITY,  line 113 of emlparser.pas
  $00424930  TEMLPARSER__PARSEENTITIES,  line 100 of emlparser.pas
  $00424872  TEMLPARSER__PARSEERD,  line 86 of emlparser.pas
  $00425301  TEMLPARSER__PARSE,  line 238 of emlparser.pas
  $00401653  main,  line 25 of emlc.lpr
  $0040CDB1
Call trace for block $0005F3D0 size 20
  $004095B8
  $0042611F  TEMLENTITIES__ADDENTITY,  line 208 of emlast.pp
  $0042493A  TEMLPARSER__PARSEENTITIES,  line 100 of emlparser.pas
  $00424872  TEMLPARSER__PARSEERD,  line 86 of emlparser.pas
  $00425301  TEMLPARSER__PARSE,  line 238 of emlparser.pas
  $00401653  main,  line 25 of emlc.lpr
  $0040CDB1
  $0040CDB1
Call trace for block $0008D970 size 264
  $00424A56  TEMLPARSER__PARSEENTITY,  line 116 of emlparser.pas
  $00424930  TEMLPARSER__PARSEENTITIES,  line 100 of emlparser.pas
  $00424872  TEMLPARSER__PARSEERD,  line 86 of emlparser.pas
  $00425301  TEMLPARSER__PARSE,  line 238 of emlparser.pas
  $00401653  main,  line 25 of emlc.lpr
  $0040CDB1
Call trace for block $0008D820 size 261
  $00424B4E  TEMLPARSER__PARSEFIELD,  line 130 of emlparser.pas
  $00424BBC  TEMLPARSER__PARSEFIELDS,  line 139 of emlparser.pas
  $00424A1B  TEMLPARSER__PARSEENTITY,  line 113 of emlparser.pas
  $00424930  TEMLPARSER__PARSEENTITIES,  line 100 of emlparser.pas
  $00424872  TEMLPARSER__PARSEERD,  line 86 of emlparser.pas
  $00425301  TEMLPARSER__PARSE,  line 238 of emlparser.pas
  $00401653  main,  line 25 of emlc.lpr
  $0040CDB1
Call trace for block $0008D6D0 size 261
  $00424B4E  TEMLPARSER__PARSEFIELD,  line 130 of emlparser.pas
  $00424BBC  TEMLPARSER__PARSEFIELDS,  line 139 of emlparser.pas
  $00424A1B  TEMLPARSER__PARSEENTITY,  line 113 of emlparser.pas
  $00424930  TEMLPARSER__PARSEENTITIES,  line 100 of emlparser.pas
  $00424872  TEMLPARSER__PARSEERD,  line 86 of emlparser.pas
  $00425301  TEMLPARSER__PARSE,  line 238 of emlparser.pas
  $00401653  main,  line 25 of emlc.lpr
  $0040CDB1
Call trace for block $0005F010 size 20
  $004095B8
  $00424BAF  TEMLPARSER__PARSEFIELDS,  line 137 of emlparser.pas
  $00424A1B  TEMLPARSER__PARSEENTITY,  line 113 of emlparser.pas
  $00424930  TEMLPARSER__PARSEENTITIES,  line 100 of emlparser.pas
  $00424872  TEMLPARSER__PARSEERD,  line 86 of emlparser.pas
  $00425301  TEMLPARSER__PARSE,  line 238 of emlparser.pas
  $00401653  main,  line 25 of emlc.lpr
  $0040CDB1
Call trace for block $0008D580 size 261
  $00424B4E  TEMLPARSER__PARSEFIELD,  line 130 of emlparser.pas
  $00424BA5  TEMLPARSER__PARSEFIELDS,  line 137 of emlparser.pas
  $00424A1B  TEMLPARSER__PARSEENTITY,  line 113 of emlparser.pas
  $00424930  TEMLPARSER__PARSEENTITIES,  line 100 of emlparser.pas
  $00424872  TEMLPARSER__PARSEERD,  line 86 of emlparser.pas
  $00425301  TEMLPARSER__PARSE,  line 238 of emlparser.pas
  $00401653  main,  line 25 of emlc.lpr
  $0040CDB1
Call trace for block $0006D718 size 25
  $00424B9A  TEMLPARSER__PARSEFIELDS,  line 135 of emlparser.pas
  $00424A1B  TEMLPARSER__PARSEENTITY,  line 113 of emlparser.pas
  $00424930  TEMLPARSER__PARSEENTITIES,  line 100 of emlparser.pas
  $00424872  TEMLPARSER__PARSEERD,  line 86 of emlparser.pas
  $00425301  TEMLPARSER__PARSE,  line 238 of emlparser.pas
  $00401653  main,  line 25 of emlc.lpr
  $0040CDB1
Call trace for block $0006D6A8 size 25
  $00425FE5  TEMLENTITIES__CREATE,  line 197 of emlast.pp
  $00424908  TEMLPARSER__PARSEENTITIES,  line 95 of emlparser.pas
  $00424872  TEMLPARSER__PARSEERD,  line 86 of emlparser.pas
  $00425301  TEMLPARSER__PARSE,  line 238 of emlparser.pas
  $00401653  main,  line 25 of emlc.lpr
  $0040CDB1
Call trace for block $00075658 size 8
  $00424908  TEMLPARSER__PARSEENTITIES,  line 95 of emlparser.pas
  $00424872  TEMLPARSER__PARSEERD,  line 86 of emlparser.pas
  $00425301  TEMLPARSER__PARSE,  line 238 of emlparser.pas
  $00401653  main,  line 25 of emlc.lpr
  $0040CDB1
Call trace for block $0005E5F0 size 12
  $004015DF  main,  line 17 of emlc.lpr
  $0040CDB1
Call trace for block $0005E590 size 19
  $004015CD  main,  line 17 of emlc.lpr
  $0040CDB1
Could anyone help me?

bobc

  • New Member
  • *
  • Posts: 41
Re: Access violation on Free
« Reply #1 on: September 01, 2010, 08:37:52 pm »
Clearly a function which raises an exception does not return the result you are expecting, in my tests it appears to return 0 or nil depending on type.

I don't know what the language spec says, I could not find a reference to this.

In general I would not expect that after an exception any results from an inner function or procedure could be relied on (i.e. result or var parameters).

On a style note, it could be considered debatable whether end of file is an unexpected condition. Sure its an error condition, just maybe not an exception?

Either way, I would prefer to deallocate resources closer to where they are allocated, especially in an exception condition.

In a recursive descent parser, an end of file condition could be handled by ending the current block normally. This would leave a sane parse tree even if not syntactically valid.

Leledumbo

  • Hero Member
  • *****
  • Posts: 8718
  • Programming + Glam Metal + Tae Kwon Do = Me
Re: Access violation on Free
« Reply #2 on: September 03, 2010, 06:24:00 am »
Quote
On a style note, it could be considered debatable whether end of file is an unexpected condition. Sure its an error condition, just maybe not an exception?

Either way, I would prefer to deallocate resources closer to where they are allocated, especially in an exception condition.

In a recursive descent parser, an end of file condition could be handled by ending the current block normally. This would leave a sane parse tree even if not syntactically valid.
After re-thinking, I thought the use of exception is indeed overkill. All methods would automatically stop when it encounters unexpected token, in this case the end of file. I'll try removing the exception to see whether it could cause infinite loop or not.

 

TinyPortal © 2005-2018