diff options
Diffstat (limited to 'source/blender/blenloader/intern/writefile.c')
-rw-r--r-- | source/blender/blenloader/intern/writefile.c | 45 |
1 files changed, 20 insertions, 25 deletions
diff --git a/source/blender/blenloader/intern/writefile.c b/source/blender/blenloader/intern/writefile.c index 19fb80ffb66..7933f5450f3 100644 --- a/source/blender/blenloader/intern/writefile.c +++ b/source/blender/blenloader/intern/writefile.c @@ -2911,43 +2911,41 @@ static void write_uilist(WriteData *wd, uiList *ui_list) } } -static void write_soops(WriteData *wd, SpaceOops *so, LinkNode **tmp_mem_list) +static void write_soops(WriteData *wd, SpaceOops *so) { BLI_mempool *ts = so->treestore; if (ts) { + SpaceOops so_flat = *so; + int elems = BLI_mempool_count(ts); /* linearize mempool to array */ TreeStoreElem *data = elems ? BLI_mempool_as_arrayN(ts, "TreeStoreElem") : NULL; if (data) { - TreeStore *ts_flat = MEM_callocN(sizeof(TreeStore), "TreeStore"); + /* In this block we use the memory location of the treestore + * but _not_ its data, the addresses in this case are UUID's, + * since we can't rely on malloc giving us different values each time. + */ + TreeStore ts_flat = {0}; - ts_flat->usedelem = elems; - ts_flat->totelem = elems; - ts_flat->data = data; + /* we know the treestore is at least as big as a pointer, + * so offsetting works to give us a UUID. */ + void *data_addr = (void *)POINTER_OFFSET(ts, sizeof(void *)); - /* temporarily replace mempool-treestore by flat-treestore */ - so->treestore = (BLI_mempool *)ts_flat; - writestruct(wd, DATA, SpaceOops, 1, so); + ts_flat.usedelem = elems; + ts_flat.totelem = elems; + ts_flat.data = data_addr; - writestruct(wd, DATA, TreeStore, 1, ts_flat); - writestruct(wd, DATA, TreeStoreElem, elems, data); + writestruct(wd, DATA, SpaceOops, 1, so); - /* we do not free the pointers immediately, because if we have multiple - * outliners in a screen we might get the same address on the next - * malloc, which makes the address no longer unique and so invalid for - * lookups on file read, causing crashes or double frees */ - BLI_linklist_prepend(tmp_mem_list, ts_flat); - BLI_linklist_prepend(tmp_mem_list, data); + writestruct_at_address(wd, DATA, TreeStore, 1, ts, &ts_flat); + writestruct_at_address(wd, DATA, TreeStoreElem, elems, data_addr, data); } else { - so->treestore = NULL; - writestruct(wd, DATA, SpaceOops, 1, so); + so_flat.treestore = NULL; + writestruct_at_address(wd, DATA, SpaceOops, 1, so, &so_flat); } - - /* restore old treestore */ - so->treestore = ts; } else { writestruct(wd, DATA, SpaceOops, 1, so); @@ -2960,7 +2958,6 @@ static void write_screens(WriteData *wd, ListBase *scrbase) ScrArea *sa; ScrVert *sv; ScrEdge *se; - LinkNode *tmp_mem_list = NULL; sc = scrbase->first; while (sc) { @@ -3064,7 +3061,7 @@ static void write_screens(WriteData *wd, ListBase *scrbase) } else if (sl->spacetype == SPACE_OUTLINER) { SpaceOops *so = (SpaceOops *)sl; - write_soops(wd, so, &tmp_mem_list); + write_soops(wd, so); } else if (sl->spacetype == SPACE_IMAGE) { writestruct(wd, DATA, SpaceImage, 1, sl); @@ -3132,8 +3129,6 @@ static void write_screens(WriteData *wd, ListBase *scrbase) sc = sc->id.next; } - BLI_linklist_freeN(tmp_mem_list); - /* flush helps the compression for undo-save */ mywrite(wd, MYWRITE_FLUSH, 0); } |