|
|
> 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
|
|