POV-Ray : Newsgroups : povray.general : POV-file that crashes POV-Ray : Re: POV-file that crashes POV-Ray Server Time
10 Aug 2024 09:18:44 EDT (-0400)
  Re: POV-file that crashes POV-Ray  
From: Nigel Stewart
Date: 17 Mar 2000 22:04:07
Message: <38D2F1D3.6D076C27@nigels.com>
>         The bug is real - I'm chasing it now.

	I havn't managed to find a fix, but I'll post here
	a more detailed description, which I hope will 
	be helpful to people more familiar with the POV
	parser, and the macro and local functionality
	in particular.

	The problem seems to be that a macro that 
	emits data on the basis of a local, can
	leave a dangling pointer.  Sometimes this
	pointer is still pointing at the right
	value, sometimes it is pointing at
	garbage - it depends on the C runtime
	library being used for memory management.

	Here is a simpler POV scene that does not
	crash POV (Windows binary, or my compiled
	command line binaries with VC++ 6.0) but
	still acesses dangling pointers.  Note
	that it is not specific to arrays or
	recursion of the same macro.

#version 3.1;

#macro Macro1(A)
  #local B = A;
  B
#end

#macro Macro2(C)
  #local D = C;
  D
#end

#local Z = Macro1(Macro2(1.0));

	When the parser attempts to get the data
	associated with "A" when emitting Macro1,
	Purify catches a "freed memory access".
	It seems that the data was freed when
	Macro2 completes processing and the
	symbol table for it is destroyed.

	Here is the full detail of the purify
	report:

[E] FMR: Free memory read in Read_Symbol {1 occurrence}
    Reading 4 bytes from 0x023307fc (4 bytes at 0x023307fc illegal)
    Address 0x023307fc is 36 bytes into a 40 byte block at 0x023307d8
    Address 0x023307fc points to a malloc'd block in heap 0x022f0000
    Thread ID: 0xc1
    Error location
        Read_Symbol    [TOKENIZE.C:1880]
                           else
                           {
                             Par             = (POV_PARAM
*)(Temp_Entry->Data);
             =>              Token.Token_Id  = *(Par->NumberPtr);
                             Token.NumberPtr = Par->NumberPtr;
                             Token.DataPtr   = Par->DataPtr;
                           }
        Get_Token      [TOKENIZE.C:1171]
                      case 'Z':
                      case '_':
                        Echo_ungetc(c);
             =>         Read_Symbol ();
                        break;
                      case '\t':
                      case '\r':
        Parse_RValue   [PARSE.C:4908]
                  int Old_Ok=Ok_To_Declare;
                  int Terms;
                
             =>   EXPECT
                    CASE4 (TNORMAL_ID_TOKEN, FINISH_ID_TOKEN,
TEXTURE_ID_TOKEN, OBJECT_ID_TOKEN)
                    CASE4 (COLOUR_MAP_ID_TOKEN, TRANSFORM_ID_TOKEN,
CAMERA_ID_TOKEN, PIGMENT_ID_TOKEN)
                    CASE4
(SLOPE_MAP_ID_TOKEN,NORMAL_MAP_ID_TOKEN,TEXTURE_MAP_ID_TOKEN,ARRAY_ID_TOKEN)
        Parse_Declare  [PARSE.C:4880]
        Parse_Directive [TOKENIZE.C:2422]
        Get_Token      [TOKENIZE.C:988]
        Parse_RValue   [PARSE.C:4908]
        Parse_Declare  [PARSE.C:4880]
        Parse_Directive [TOKENIZE.C:2422]
        Get_Token      [TOKENIZE.C:988]
    Allocation location
        malloc         [dbgheap.c:129]
        pov_malloc     [mem.c:323]
        Create_Entry   [TOKENIZE.C:3006]
                {
                  SYM_ENTRY *New;
                
             =>   New = (SYM_ENTRY *)POV_MALLOC(sizeof(SYM_ENTRY),
"symbol table entry");
                #if 0
                  printf("Create_Entry index: %d name: %s number: %d 
entry: %d\n",Index,Name,Number,New);
                #endif
        Add_Symbol     [TOKENIZE.C:3070]
                {
                  SYM_ENTRY *New;
                
             =>   New = Create_Entry (Index,Name,Number);
                  Add_Entry(Index,New);
                
                  return(New);
        Parse_Declare  [PARSE.C:4817]
                
                  EXPECT
                    CASE (IDENTIFIER_TOKEN)
             =>       Temp_Entry = Add_Symbol
(Local_Index,Token.Token_String,IDENTIFIER_TOKEN);
                      Token.NumberPtr = &(Temp_Entry->Token_Number);
                      Token.DataPtr   = &(Temp_Entry->Data);
                      Previous        = Token.Token_Id;
        Parse_Directive [TOKENIZE.C:2422]
                      }
                      else
                      {
             =>          Parse_Declare ();
                         Curr_Type = Cond_Stack[CS_Index].Cond_Type;
                         if (Token.Unget_Token)
                         {
        Get_Token      [TOKENIZE.C:988]
        Parse_RValue   [PARSE.C:4908]
        Invoke_Macro   [TOKENIZE.C:3258]
        Read_Symbol    [TOKENIZE.C:1816]
    Free location
        free           [dbgheap.c:955]
        pov_free       [mem.c:545]
        Destroy_Entry  [TOKENIZE.C:3049]
                
                   Destroy_Ident_Data (Entry->Data,Entry->Token_Number);
                
             =>    POV_FREE(Entry);
                
                   return(Next);
                }
        Destroy_Table  [TOKENIZE.C:2989]
                
                      while (Entry)
                      {
             =>          Entry = Destroy_Entry(Entry);
                      }
                
                      Table->Table[i] = NULL;
        Return_From_Macro [TOKENIZE.C:3355]
                  }
                
                  /* Always destroy macro locals */
             =>   Destroy_Table(Table_Index--);
                }
                
                void Destroy_Macro(POV_MACRO *PMac)
        Parse_Directive [TOKENIZE.C:2095]
        Get_Token      [TOKENIZE.C:988]
        Parse_Num_Factor [express.c:707]
        Parse_Num_Term [express.c:875]
        Parse_Rel_Factor [express.c:940]

I hope it helps.
I'm off to the beach!

Nigel

--
Nigel Stewart (nig### [at] nigelscom)
Research Student, Software Developer
Y2K is the new millenium for the mathematically challenged.


Post a reply to this message

Copyright 2003-2023 Persistence of Vision Raytracer Pty. Ltd.