Blender crashes during script execution

Hi, everybody. At some point, I noticed that Blender crashes when working with the add-on.

Error: EXCEPTION_ACCESS_VIOLATION
Address: 0x00007FF6B1237C13
Module : D:\blender-2.81a-windows64\blender-2.81a-windows64\blender.exe

A similar problem occurs in version 2.82.7. Several people had the problem.
I don’t know what to do with it. No matter how much I check, the addon looks stable.

The problem itself appears at random times. I ran an autocliker that performed operations using the addon for 12 hours in debug mode, but the problem did not appear (perhaps because there was a delay during testing due to the output of debug data to the console).

I have doubts about recursion. I recursively search for child collections to get collections as LayerCollection, because the Collection type does not have a property that is responsible for visibility in the viewport. But since this is my first time dealing with recursion, I have my doubts about it.

Maybe someone got a similar error?

The addon can be found here: https://gumroad.com/l/bt_hide

Alt+H - unhide objects everywhere except hidden collections (by default, Alt+H displays objects on hidden collections as well).

Without even looking at your code I can pretty much guarantee you’re either changing a prop collection in a loop or storing direct data references and trying to recall them later. When I’m not on an iPad I’ll pull down your script and take a look if someone else doesn’t beat me to it, but in the meantime have a look at the ‘gotchas’ page in the api docs.

I think I understand the problem.
The exception is caused by changing the collection cache when I change the states of objects (obj.hide_set) in this collection. And this causes an error when accessing the collection data inside this loop?

So I need to write all the objects for processing somewhere first and then change their properties?

I just went to check your code- could you put it on pastebin.org or something so I don’t have to create a gumroad account? or- if it’s just a single script you could probably just attach it here.

https://pastebin.com/mC3F9Gmj - __init__.py
https://pastebin.com/7v6MpnH6 - bt_hide.py

I suspect you’re crashing due to storing direct references to data in a loop and then recalling it elsewhere. I think if everything was within the same scope you would be fine, but you’ve got stuff in global, a nested function, etc. It’s entirely possible that on some machines, blender is freeing the memory used by your references when you leave a particular scope, and later when you try to access that reference the memory is being used by something else and you get an access violation.

The safer way to do this is, instead of storing direct references to the data, store a list of strings that you can use to get guaranteed references to the data you’re after.

in other words, instead of:

all_collections.append(child)

do this:

all_collections.append(child.name)

then later when you need to recall the collection object, use

bpy.data.collections[all_collections[index]]

Thanks.
I hope this nightmare is over :slight_smile: I Really don’t like bugs that can’t be caused intentionally.

I also made a few more changes to fix various unpleasant things.
I found that the all_collections variable was never overwritten throughout the session. It turns out that each call to my list simply added new elements and loops could be tens or hundreds of times to pass through the same collections.

It is strange that during the 12-hour test, the blender did not fall after using up all the memory.

I can’t see anything immediately wrong with the script.

While recursion may be slightly faster, there’s a chance of hitting a recursion limit. Although it can be increased using sys.setrecursionlimit(), it will also increase the risk of a stack overflow. The fact that you’re not handling a possible recursion means there’s also a chance of not getting all layer collections in a large scene.

An alternate method is using sets and a while loop:

import bpy

lc_top = bpy.context.view_layer.layer_collection

visibles = set()
pool = {*lc_top.children}

while pool:
    c = pool.pop()
    if c.visible_get():
        visibles.add(c)
        pool.update(c.children)