JohnSwafford
12-17-2006, 02:39 AM
I've found a bug in the deleteTrackViewNode() function that I want to confirm in MAX 9, but I don't have it installed. If anyone could run the script below in MAX 9 and post the Listener output in this thread, it would confirm whether its still around. (Make sure to do a Reset before and after running the script.)
(
global MyTVnodeArray = #(), CheckNodeStates
fn CheckNodeStates note AvoidLast:false =
(
local NodeCount = MyTVnodeArray.count
local StoredNames = "", ArrRefNameProp = "", InterfaceNameProp = ""
for i=1 to NodeCount do (StoredNames+=((MyTVnodeArray[i][1])+","))
for i=1 to NodeCount do (ArrRefNameProp+=(if ((i==NodeCount)AND(AvoidLast)AND(((maxVersion())[1])<5000)) then ("-CRASH-") else (try(MyTVnodeArray[i][2].name)catch("!ERROR!"))+","))
for i=1 to NodeCount do (InterfaceNameProp+=((try((execute ("trackViewNodes."+(MyTVnodeArray[i][1]))).name)catch("!ERROR!"))+","))
format "%:\n" note
format " Stored Strings: %\n" StoredNames
format " TrackRefs.name: %\n" ArrRefNameProp
format " Interface.name: %\n" InterfaceNameProp
)
for i=1 to 5 do
(
MyTVnodeArray[i] = #()
MyTVnodeArray[i][2] = (newTrackViewNode trackViewNodes ("MyNode"+(i as string)))
MyTVnodeArray[i][1] = (MyTVnodeArray[i][2].name)
)
CheckNodeStates "Nodes Created"
deleteTrackViewNode (trackViewNodes) (trackViewNodes.MyNode2)
--This line CORRUPTS the Node Refs!
CheckNodeStates "MyNode2 Deleted" AvoidLast:true
--This function call should trigger the catch() code block for MyNode2, because
--the try() code block is trying to access the .name property of a deleted node.
--However, the function actually accesses the .name property of MyNode3 instead
--of the "!ERROR!" string from the catch() block.
deleteItem MyTVnodeArray 2
--The MyNode2 name string and reference are removed from the array.
CheckNodeStates "Array Member Deleted" AvoidLast:true
local newtrak = (newTrackViewNode trackViewNodes "MyNode6")
CheckNodeStates "MyNode6 Created"
--The creation of MyNode6 somehow affects the original MyNode5 reference.
MyTVnodeArray[5] = #()
MyTVnodeArray[5][2] = newtrak
MyTVnodeArray[5][1] = (MyTVnodeArray[5][2].name)
CheckNodeStates "MyNode6 Added to Array"
)
DETAILS: The script above creates several custom nodes in TrackView and stores references to them in an array. The deleteTrackViewNode() function seems to corrupt the references to the deleted node AND (in MAX 3-5) the other references as well. Instead of the reference to the deleted node being invalid/inaccessible, it points instead to the next node in Track View.
I've tested this script in MAX 3-8, and the bug appears to be present in various forms in all of them. In MAX 3/4, the bug would corrupt the deleted reference, the other references AND could actually crash MAX completely if the last node reference in the array was accessed. (The script above is safeguarded against this.) In MAX 5, the bug would corrupt the deleted reference and the other reference, but would not cause any crashes. In MAX6-8, the bug would only corrupt the reference to the deleted node.
I've already coded a workaround for myself, and the behavior in MAX 6-8 isn't nearly as bad as MAX 3-5....but this definitely looks wrong. Shown below are the Listener outputs from various MAX versions....the yellow text shows the extent of the corruption in each version.
MAX 3/4
Nodes Created:
Stored Strings: MyNode1,MyNode2,MyNode3,MyNode4,MyNode5,
TrackRefs.name: MyNode1,MyNode2,MyNode3,MyNode4,MyNode5,
Interface.name: MyNode1,MyNode2,MyNode3,MyNode4,MyNode5,
MyNode2 Deleted:
Stored Strings: MyNode1,MyNode2,MyNode3,MyNode4,MyNode5,
TrackRefs.name: MyNode1,MyNode3,MyNode4,MyNode5,-CRASH-
Interface.name: MyNode1,!ERROR!,MyNode3,MyNode4,MyNode5,
Array Member Deleted:
Stored Strings: MyNode1,MyNode3,MyNode4,MyNode5,
TrackRefs.name: MyNode1,MyNode4,MyNode5,-CRASH-
Interface.name: MyNode1,MyNode3,MyNode4,MyNode5,
MyNode6 Created:
Stored Strings: MyNode1,MyNode3,MyNode4,MyNode5,
TrackRefs.name: MyNode1,MyNode4,MyNode5,MyNode6,
Interface.name: MyNode1,MyNode3,MyNode4,MyNode5,
MyNode6 Added to Array:
Stored Strings: MyNode1,MyNode3,MyNode4,MyNode5,MyNode6,
TrackRefs.name: MyNode1,MyNode4,MyNode5,MyNode6,MyNode6,
Interface.name: MyNode1,MyNode3,MyNode4,MyNode5,MyNode6,
OK
MAX 5
Nodes Created:
Stored Strings: MyNode1,MyNode2,MyNode3,MyNode4,MyNode5,
TrackRefs.name: MyNode1,MyNode2,MyNode3,MyNode4,MyNode5,
Interface.name: MyNode1,MyNode2,MyNode3,MyNode4,MyNode5,
MyNode2 Deleted:
Stored Strings: MyNode1,MyNode2,MyNode3,MyNode4,MyNode5,
TrackRefs.name: MyNode1,MyNode3,MyNode4,MyNode5,MyNode5,
Interface.name: MyNode1,!ERROR!,MyNode3,MyNode4,MyNode5,
Array Member Deleted:
Stored Strings: MyNode1,MyNode3,MyNode4,MyNode5,
TrackRefs.name: MyNode1,MyNode4,MyNode5,MyNode5,
Interface.name: MyNode1,MyNode3,MyNode4,MyNode5,
MyNode6 Created:
Stored Strings: MyNode1,MyNode3,MyNode4,MyNode5,
TrackRefs.name: MyNode1,MyNode4,MyNode5,MyNode6,
Interface.name: MyNode1,MyNode3,MyNode4,MyNode5,
MyNode6 Added to Array:
Stored Strings: MyNode1,MyNode3,MyNode4,MyNode5,MyNode6,
TrackRefs.name: MyNode1,MyNode4,MyNode5,MyNode6,MyNode6,
Interface.name: MyNode1,MyNode3,MyNode4,MyNode5,MyNode6,
OK
MAX 6/7/8
Nodes Created:
Stored Strings: MyNode1,MyNode2,MyNode3,MyNode4,MyNode5,
TrackRefs.name: MyNode1,MyNode2,MyNode3,MyNode4,MyNode5,
Interface.name: MyNode1,MyNode2,MyNode3,MyNode4,MyNode5,
MyNode2 Deleted:
Stored Strings: MyNode1,MyNode2,MyNode3,MyNode4,MyNode5,
TrackRefs.name: MyNode1,MyNode3,MyNode3,MyNode4,MyNode5,
Interface.name: MyNode1,!ERROR!,MyNode3,MyNode4,MyNode5,
Array Member Deleted:
Stored Strings: MyNode1,MyNode3,MyNode4,MyNode5,
TrackRefs.name: MyNode1,MyNode3,MyNode4,MyNode5,
Interface.name: MyNode1,MyNode3,MyNode4,MyNode5,
MyNode6 Created:
Stored Strings: MyNode1,MyNode3,MyNode4,MyNode5,
TrackRefs.name: MyNode1,MyNode3,MyNode4,MyNode5,
Interface.name: MyNode1,MyNode3,MyNode4,MyNode5,
MyNode6 Added to Array:
Stored Strings: MyNode1,MyNode3,MyNode4,MyNode5,MyNode6,
TrackRefs.name: MyNode1,MyNode3,MyNode4,MyNode5,MyNode6,
Interface.name: MyNode1,MyNode3,MyNode4,MyNode5,MyNode6,
OK
(
global MyTVnodeArray = #(), CheckNodeStates
fn CheckNodeStates note AvoidLast:false =
(
local NodeCount = MyTVnodeArray.count
local StoredNames = "", ArrRefNameProp = "", InterfaceNameProp = ""
for i=1 to NodeCount do (StoredNames+=((MyTVnodeArray[i][1])+","))
for i=1 to NodeCount do (ArrRefNameProp+=(if ((i==NodeCount)AND(AvoidLast)AND(((maxVersion())[1])<5000)) then ("-CRASH-") else (try(MyTVnodeArray[i][2].name)catch("!ERROR!"))+","))
for i=1 to NodeCount do (InterfaceNameProp+=((try((execute ("trackViewNodes."+(MyTVnodeArray[i][1]))).name)catch("!ERROR!"))+","))
format "%:\n" note
format " Stored Strings: %\n" StoredNames
format " TrackRefs.name: %\n" ArrRefNameProp
format " Interface.name: %\n" InterfaceNameProp
)
for i=1 to 5 do
(
MyTVnodeArray[i] = #()
MyTVnodeArray[i][2] = (newTrackViewNode trackViewNodes ("MyNode"+(i as string)))
MyTVnodeArray[i][1] = (MyTVnodeArray[i][2].name)
)
CheckNodeStates "Nodes Created"
deleteTrackViewNode (trackViewNodes) (trackViewNodes.MyNode2)
--This line CORRUPTS the Node Refs!
CheckNodeStates "MyNode2 Deleted" AvoidLast:true
--This function call should trigger the catch() code block for MyNode2, because
--the try() code block is trying to access the .name property of a deleted node.
--However, the function actually accesses the .name property of MyNode3 instead
--of the "!ERROR!" string from the catch() block.
deleteItem MyTVnodeArray 2
--The MyNode2 name string and reference are removed from the array.
CheckNodeStates "Array Member Deleted" AvoidLast:true
local newtrak = (newTrackViewNode trackViewNodes "MyNode6")
CheckNodeStates "MyNode6 Created"
--The creation of MyNode6 somehow affects the original MyNode5 reference.
MyTVnodeArray[5] = #()
MyTVnodeArray[5][2] = newtrak
MyTVnodeArray[5][1] = (MyTVnodeArray[5][2].name)
CheckNodeStates "MyNode6 Added to Array"
)
DETAILS: The script above creates several custom nodes in TrackView and stores references to them in an array. The deleteTrackViewNode() function seems to corrupt the references to the deleted node AND (in MAX 3-5) the other references as well. Instead of the reference to the deleted node being invalid/inaccessible, it points instead to the next node in Track View.
I've tested this script in MAX 3-8, and the bug appears to be present in various forms in all of them. In MAX 3/4, the bug would corrupt the deleted reference, the other references AND could actually crash MAX completely if the last node reference in the array was accessed. (The script above is safeguarded against this.) In MAX 5, the bug would corrupt the deleted reference and the other reference, but would not cause any crashes. In MAX6-8, the bug would only corrupt the reference to the deleted node.
I've already coded a workaround for myself, and the behavior in MAX 6-8 isn't nearly as bad as MAX 3-5....but this definitely looks wrong. Shown below are the Listener outputs from various MAX versions....the yellow text shows the extent of the corruption in each version.
MAX 3/4
Nodes Created:
Stored Strings: MyNode1,MyNode2,MyNode3,MyNode4,MyNode5,
TrackRefs.name: MyNode1,MyNode2,MyNode3,MyNode4,MyNode5,
Interface.name: MyNode1,MyNode2,MyNode3,MyNode4,MyNode5,
MyNode2 Deleted:
Stored Strings: MyNode1,MyNode2,MyNode3,MyNode4,MyNode5,
TrackRefs.name: MyNode1,MyNode3,MyNode4,MyNode5,-CRASH-
Interface.name: MyNode1,!ERROR!,MyNode3,MyNode4,MyNode5,
Array Member Deleted:
Stored Strings: MyNode1,MyNode3,MyNode4,MyNode5,
TrackRefs.name: MyNode1,MyNode4,MyNode5,-CRASH-
Interface.name: MyNode1,MyNode3,MyNode4,MyNode5,
MyNode6 Created:
Stored Strings: MyNode1,MyNode3,MyNode4,MyNode5,
TrackRefs.name: MyNode1,MyNode4,MyNode5,MyNode6,
Interface.name: MyNode1,MyNode3,MyNode4,MyNode5,
MyNode6 Added to Array:
Stored Strings: MyNode1,MyNode3,MyNode4,MyNode5,MyNode6,
TrackRefs.name: MyNode1,MyNode4,MyNode5,MyNode6,MyNode6,
Interface.name: MyNode1,MyNode3,MyNode4,MyNode5,MyNode6,
OK
MAX 5
Nodes Created:
Stored Strings: MyNode1,MyNode2,MyNode3,MyNode4,MyNode5,
TrackRefs.name: MyNode1,MyNode2,MyNode3,MyNode4,MyNode5,
Interface.name: MyNode1,MyNode2,MyNode3,MyNode4,MyNode5,
MyNode2 Deleted:
Stored Strings: MyNode1,MyNode2,MyNode3,MyNode4,MyNode5,
TrackRefs.name: MyNode1,MyNode3,MyNode4,MyNode5,MyNode5,
Interface.name: MyNode1,!ERROR!,MyNode3,MyNode4,MyNode5,
Array Member Deleted:
Stored Strings: MyNode1,MyNode3,MyNode4,MyNode5,
TrackRefs.name: MyNode1,MyNode4,MyNode5,MyNode5,
Interface.name: MyNode1,MyNode3,MyNode4,MyNode5,
MyNode6 Created:
Stored Strings: MyNode1,MyNode3,MyNode4,MyNode5,
TrackRefs.name: MyNode1,MyNode4,MyNode5,MyNode6,
Interface.name: MyNode1,MyNode3,MyNode4,MyNode5,
MyNode6 Added to Array:
Stored Strings: MyNode1,MyNode3,MyNode4,MyNode5,MyNode6,
TrackRefs.name: MyNode1,MyNode4,MyNode5,MyNode6,MyNode6,
Interface.name: MyNode1,MyNode3,MyNode4,MyNode5,MyNode6,
OK
MAX 6/7/8
Nodes Created:
Stored Strings: MyNode1,MyNode2,MyNode3,MyNode4,MyNode5,
TrackRefs.name: MyNode1,MyNode2,MyNode3,MyNode4,MyNode5,
Interface.name: MyNode1,MyNode2,MyNode3,MyNode4,MyNode5,
MyNode2 Deleted:
Stored Strings: MyNode1,MyNode2,MyNode3,MyNode4,MyNode5,
TrackRefs.name: MyNode1,MyNode3,MyNode3,MyNode4,MyNode5,
Interface.name: MyNode1,!ERROR!,MyNode3,MyNode4,MyNode5,
Array Member Deleted:
Stored Strings: MyNode1,MyNode3,MyNode4,MyNode5,
TrackRefs.name: MyNode1,MyNode3,MyNode4,MyNode5,
Interface.name: MyNode1,MyNode3,MyNode4,MyNode5,
MyNode6 Created:
Stored Strings: MyNode1,MyNode3,MyNode4,MyNode5,
TrackRefs.name: MyNode1,MyNode3,MyNode4,MyNode5,
Interface.name: MyNode1,MyNode3,MyNode4,MyNode5,
MyNode6 Added to Array:
Stored Strings: MyNode1,MyNode3,MyNode4,MyNode5,MyNode6,
TrackRefs.name: MyNode1,MyNode3,MyNode4,MyNode5,MyNode6,
Interface.name: MyNode1,MyNode3,MyNode4,MyNode5,MyNode6,
OK
