#Alloc and free behavior

1 messages · Page 1 of 1 (latest)

whole pendant
#

I have a need to allocate X amount of structs that will need to be stored for later and I am confused about allocations using .alloc() method.

Here is example of code that I would like to understand, using ArenaAllocator:

const boxes = try self.boxAllocator.allocator().alloc(Box, items.len);
defer self.boxAllocator.allocator().free(boxes);

Questions I have:

  • Is this a correct pattern to create X amout of items?
  • does .free returns memory of slice structure and individual Box items inside slice? (basically takes care of both)
  • since I may need items in slice for later, do I have to apply .free operation in same scope? how do I free the slice, but not the items in slice?

My confusion stems from fact that I see slice and items inside the slice as two separate data structures that need memory, hence I would appreciate clarification about should I even care about slice as separate construct?

sterile oxide
#

the slice itself lives on the stack (the pointer and the length), the allocated memory lives on wherever the allocator decides, so if you let boxes out of scope without copying it somewhere and do not free it when the scope ends, you have a memory leak. With that in mind:

  1. yes, alloc is the correct call for creating an array that is allocated dynamically, whose items are to be considered to be initialized with undefined, so you have to initialize those items before you use them
  2. as explained above, the slice itself lives on the stack, so it won't be freed by free, free only frees the memory pointed to by the slice
  3. you don't have to call free in the same scope, you just have to keep slice with you so that you can use it and deallocate it when you deem appropriate to do so
dawn comet
sterile oxide
#

yeah, I was explaining in general, for arena, it's not considered leaked

whole pendant
sterile oxide
#

I think you need to rethink about slices, slices are only pointers, nothing lives in them beside pointers and lengths

#

a slice is basically struct {ptr: [*]T, len: usize}

#

so the lifetimes of a slice and the memory it points to are completely separate

whole pendant
#

ok, would it be faster to use alloc with slice versus individual create, since later does not need a slice?

sterile oxide
#

generally, it's faster to allocate a bunch of memory at a time instead of allocating memory many times

#

the problem is not a slice being created or not

#

the problem is how many times memory allocation is being done

#

like allocating 128KB 1 time is much faster than allocating 1KB 128 times

#

also memory fragmentation will happen with the latter case, which makes accessing the items slower also

#

but for arena, most likely it doesn't matter

hollow gull
whole pendant
# hollow gull just fyi, that to free memory the allocator needs to be given the same pointer a...

Would it matter if I have another slice created (say combined multiple slices together by other means) with same memory structs that were in original slice? Basically take slice with references, references get assigned to other places, but ultimately some of references end up in another slice, to be freed.

Case example:

  • boxes are created and now get used by data structure that employs ArrayList
  • some items on ArrayList need to be removed and subsequently destroyed
  • these come as slice on ArrayList items field (say I use particular index to cut a slice, so I can shrink via shrinkRetainingCapacity)
hollow gull
#

again it doesnt matter since you use an arena, but for other allocators you need to have, or be able to recreate, the original slice, it must have the same pointer and length.
Otherwise freeing it is invalid, the DebugAllocator will catch this, but other allocators may do un intended and incorrect behaviour.

whole pendant
hollow gull
#

no, you can only free the slice as a whole

whole pendant