[Closed] another – Unknown system exception
Hi,
So I get – Unknown system exception << on my script. This is really weird because the error does not appear every time, just sometimes. So this gives me no idea whats wrong.
The code itself is ok. It looks like max has issues with deleting objects…
Here is a simplified code (sorry for the language, I hope you dont mind)
try(destroyDialog WTF)catch()
rollout WTF "" (
global ThisIsIt
fn makeObj = (
sphere radius:10 name:"SuperOwesomeObject"
)
button _doIt "press the F button"
on _doIt pressed do (
for obj in geometry do (
if obj.name == "SuperOwesomeObject" do delete obj
)
makeObj()
)
)createDialog WTF
P.S. Im using max2016. But I just tested the script in max2017 and it gave me completely different feedback, this is the error I got:
-- MAXScript Rollout Handler Exception:
-- Known system exception
-- ########################################################################
-- Address: 0x0; nCode: 0x00000000C0000005
-- Desc: EXCEPTION_ACCESS_VIOLATION The thread tried to read from or write to a virtual address for which it does not have the appropriate access.
-- Write of Address: 0x0000000100000000
-- ########################################################################
-- MAXScript callstack:
-- thread data: threadID:3708
-- ------------------------------------------------------
-- [stack level: 0]
-- In _doIt.pressed(); filename: ; position: 291; line: 14
-- member of: Rollout:WTF
-- Locals:
-- Externals:
-- owner: Rollout:WTF
-- WTF: Rollout:WTF
-- makeObj: makeObj()
-- ------------------------------------------------------
-- [stack level: 1]
-- called from top-level
-- ########################################################################
-- C++ callstack:
-- ((module-name not available)): (filename not available): (function-name not available)
-- (MAXScrpt): (filename not available): ObjectSet::find_first
-- (MAXScrpt): (filename not available): ObjectSet::find_first
-- (MAXScrpt): (filename not available): ObjectSet::map
-- (MAXScrpt): (filename not available): clear_error_source_data
-- (MAXScrpt): (filename not available): Primitive::apply
-- (MAXScrpt): (filename not available): CodeTree::eval
-- (MAXScrpt): (filename not available): Primitive::apply
-- (MAXScrpt): (filename not available): CodeTree::eval
-- (MAXScrpt): (filename not available): Generic::apply
-- (MAXScrpt): (filename not available): SourceFileWrapper::apply
-- (MAXScrpt): (filename not available): RolloutControl::call_event_handler
-- (MAXScrpt): (filename not available): RolloutControl::get_wrapped_event_handler
-- (MAXScrpt): (filename not available): InitMacroScriptDir
-- (MAXScrpt): (filename not available): InitMacroScriptDir
-- (USER32): (filename not available): DispatchMessageW
-- (USER32): (filename not available): DispatchMessageW
-- (USER32): (filename not available): GetMenuItemInfoW
-- (ntdll): (filename not available): KiUserCallbackDispatcher
-- (USER32): (filename not available): InvalidateRect
-- (USER32): (filename not available): SendMessageW
-- (USER32): (filename not available): SendMessageW
-- (core): (filename not available): GetICustButton
-- (core): (filename not available): CustomControl::WindowProc
-- (core): (filename not available): AncestorIsCUIToolbarWindow
-- (USER32): (filename not available): DispatchMessageW
-- (USER32): (filename not available): DispatchMessageW
-- (USER32): (filename not available): IsDialogMessageW
-- (3dsmax): (filename not available): XMLAnimTreeEntry::GetType
-- ((module-name not available)): (filename not available): (function-name not available)
-- ((module-name not available)): (filename not available): (function-name not available)
-- ((module-name not available)): (filename not available): (function-name not available)
-- ((module-name not available)): (filename not available): (function-name not available)
-- ########################################################################
P.P.S. This happens only with rollout
More efficient:
delete (for obj in geometry where obj.name == "SuperOwesomeObject" collect obj)
If you are looking for performance then the following code may perform much better in general situations. Just try them and see what fits better for your needs.
Additionally, you can so a case insensitive search with this method, and if you don’t need Undo, you can turn it off when deleting the nodes.
nodes = getnodebyname "SuperOwesomeObject" exact:true ignoreCase:false all:true
nodes = for j in nodes where superclassof j == geometryclass collect j
delete nodes
Another thing to consider, if only you will be creating/deleting these nodes, you could store them in a local array and just delete those when needed. That would be a more efficient and elegant solution.
Not if there are Helpers, Lights, etc. with the same name.
Not if there are more than 1 node with the same name.
Not if there are no nodes with that name.
At least it should be:
try (delete $SuperOwesomeObject*) catch()
Which would also fail with nodes that are not Geometry with that name.
If these nodes will only be created by this tool, I would store them in a variable, safer and cleaner.
But I have not idea how this tool will work, so it is not possible to give a good advice.
(
delete objects
for k=1 to 10000 do box name:#SuperOwesomeObject
gc()
(
t = timestamp()
h = heapfree
nodes
for k=1 to 1000 do
(
nodes = (getnodebyname "SuperOwesomeObject" exact:true ignoreCase:false all:true)
nodes = for node in nodes where iskindof node geometryclass collect node
)
format "% => time:% heap:%
" nodes.count (timestamp() - t) (h - heapfree)
)
(
t = timestamp()
h = heapfree
nodes
for k=1 to 1000 do nodes = ([B]$geometry...SuperOwesomeObject[/B])
format "% => time:% heap:%
" nodes.count (timestamp() - t) (h - heapfree)
)
)
not many people know well the path value syntax.
if anyone is interested i can explain why this difference is so big
sure the right code works. but do you understand why your code does not?
Actually I do not understand what is the difference between
for obj in geometry
and
for obj in geometry as array do
I mean yeah, the second goes through array, and the first one… Im not sure.
every new node’s name the system registers after definition, and puts in some sort of dictionary. this dictionary later is used to find new unique name for example. (it’s called in documentation Fast Node Name Lookup)
so searching by hash value is much faster than a string comparison.
but this dictionary can take name with some limitations only. it makes some names “the same” no matter than they look different… and it’s not just about case sensitivity.
for example:
delete objects
p1 = point name:"a b"
p2 = point name:"a_b"
($...'a_b').count
($...'a b').count
that’s why getNodeByName method has an optional key argument exact
Isn’t the convertion to array what makes the difference?
(
delete objects
gc()
a = undefined
it = 100
for j = 1 to 10000 do plane lengthsegs:1 widthsegs:1 name:"test"
-- ARRAYS ---------------------------------------------
st=timestamp()
for j = 1 to it do a = ($geometry...TEST) as array -- Not Case Sensitive ?
format "time:% count:%
" (timestamp()-st) a.count
st=timestamp()
for j = 1 to it do a = geometry as array
format "time:% count:%
" (timestamp()-st) a.count
st=timestamp()
for j = 1 to it do a = getnodebyname "test" all:true
format "time:% count:%
" (timestamp()-st) a.count
-------------------------------------------------------
st=timestamp()
for j = 1 to it do a = $geometry...TEST
format "time:% count:%
" (timestamp()-st) a.count
st=timestamp()
for j = 1 to it do a = geometry
format "time:% count:%
" (timestamp()-st) a.count
)
time:1159 count:10000
time:747 count:10000
time:947 count:10000
time:0 count:10000 – Not converted
time:0 count:10000 – Not converted
When there is no convertion to array, the value to cast is minimal.
Also, how do you make the path syntax case sensitive?
hmm… maybe me and Bobo only (still an active members of this community) can remember what was originally…
the ‘dictionary’ is not case sensitive. more… it ignores (substitutes) some “characters’.
many old built-in methods takes it in account. but not all…
so. DON’T name things “alternatively”!