dynamic memory management
play

Dynamic Memory Management 333 Dynamic Memory Management Process - PowerPoint PPT Presentation

Dynamic Memory Management Dynamic Memory Management 333 Dynamic Memory Management Process Memory Layout Process Memory Layout (1) Each Linux process runs within its own virtual address space tables and the MMU (if available) security due to


  1. Dynamic Memory Management Dynamic Memory Management 333

  2. Dynamic Memory Management Process Memory Layout Process Memory Layout (1) Each Linux process runs within its own virtual address space tables and the MMU (if available) security due to memory isolation 334 • The kernel pretends that each process has access to a (huge) continuous range of addresses ( ≈ 256 TiB on x86-64) • Virtual addresses are mapped to physical addresses by the kernel using page • Greatly simplifjes memory management code in the kernel and improves • Allows for useful “tricks” such as memory-mapping fjles

  3. Dynamic Memory Management addresses for each process already supports 56 bit pointers) Process Memory Layout support 48 bit pointers at the Most of the address space is unused moment mapped to the same physical The kernel also uses virtual memory Process Memory Layout (2) 335 reserved for kernel memory 0xffffffffffffffff • Part of the address space has to be kernel-space (128 TiB) 0xffff800000000000 • This kernel-space memory is • Access to this memory is restricted unused (16 EiB) • MMUs on x86-64 platforms only 0x0000800000000000 user-space • Might change in the future (Linux (128 TiB) 0x0000000000000000

  4. Dynamic Memory Management Segments can grow addresses increase) Process Memory Layout addresses decrease) segments usually grow down (i.e. 336 User-space memory is organized in seg- ments Process Memory Layout (3) 0x0000800000000000 stack • Stack segment 100s of GiB • Memory mapping segment mmap • Heap segment • BSS, data and text segments 10s of TiB heap • Stack and memory mapping bss data up to some GiB • Heap segment usually grows up (i.e. text 0x0000000000000000

  5. Dynamic Memory Management Process Memory Layout Stack Segment (1) Stack memory is typically used for objects with automatic storage duration happen increase/decrease a pointer) Fast, but infmexible memory 337 • The compiler can statically decide when allocations and deallocations must • The memory layout is known at compile-time • Allows for highly optimized code (allocations and deallocations simply • Array sizes must be known at compile-time • No dynamic data structures are possible (trees, graphs, etc.)

  6. Dynamic Memory Management %rsp, %rbp imull -8(%rbp), %eax popq %rbp ret main: pushq %rbp movq subq movl $416, %rsp call foo() movl %eax, -4(%rbp) movl -4(%rbp), %eax leave ret -4(%rbp), %eax $21, -8(%rbp) Process Memory Layout int a[100]; Stack Segment (2) Example foo.cpp int foo() { int c = 2; int d = 21; return c * d; } int main() { int b = foo(); movl return b; } foo.o foo(): pushq %rbp movq %rsp, %rbp movl $2, -4(%rbp) 338

  7. Dynamic Memory Management Process Memory Layout Heap Segment The heap is typically used for objects with dynamic storage duration Disadvantages allocation 339 • The programmer must explicitly manage allocations and deallocations • Allows much more fmexible programs • Performance impact due to non-trivial implementation of heap-based memory • Memory fragmentation • Dynamic memory allocation is error-prone • Memory leaks • Double free (deallocation) • Make use of debugging tools (GDB, ASAN (!))

  8. Dynamic Memory Management Dynamic Memory Management in C ++ Dynamic Memory Management in C ++ Mechanisms give control over the storage duration and possibly lifetime of objects 340 C ++ provides several mechanisms for dynamic memory management • Through new and delete expressions (discouraged) • Through the C functions malloc and free (discouraged) • Through smart pointers and ownership semantics (preferred) • Level of control varies by method • In all cases: Manual intervention required

  9. Dynamic Memory Management Dynamic Memory Management in C ++ The new Expression Creates and initializes objects with dynamic storage duration Explanation allocated storage 341 • Syntax: new type initializer • type must be a type • type can be an array type • initializer can be omitted • Allocates heap storage for a single object or an array of objects • Constructs and initializes a single object or an array of objects in the newly • If initializer is absent, the object is default-initialized • Returns a pointer to the object or the initial element of the array

  10. Dynamic Memory Management Dynamic Memory Management in C ++ in the array that is being destroyed Explanation expression 342 expression Every object allocated through new must be destroyed through delete The delete Expression • Syntax (single object): delete expression • expression must be a pointer created by the single-object form of the new • Syntax (array): delete[] expression • expression must be a pointer created by the array form of the new • In both cases expression may be nullptr • If expression is nullptr nothing is done • Invokes the destructor of the object that is being destroyed, or of every object • Deallocates the memory previously occupied by the object(s)

  11. Dynamic Memory Management first = next; }; } last = node; last->next = node; else first = node; if (!last) Node* node = new Node{i, nullptr}; void push_back(int i) { } } delete first; Dynamic Memory Management in C ++ Node* next = first->next; while (first != nullptr) { ~IntList() { public: Node* last; Node* first; }; Node* next; int value; struct Node { class IntList { new & delete Example 343

  12. Dynamic Memory Management Dynamic Memory Management in C ++ Memory Leaks Memory leaks can happen easily int foo(unsigned length) { int* buffer = new int[length]; /* ... do something ... */ if (condition) return 42; // MEMORY LEAK /* ... do something else ... */ delete[] buffer; return 123; } Avoid explicit memory management through new and delete whenever possible 344

  13. Dynamic Memory Management struct A { }; } delete[] buffer; // we must explicitly call the destructor a->~A(); /* ... do something with a ... */ A* a = new (buffer) A(); std::byte* buffer = new std::byte[sizeof(A)]; int main() { #include <cstddef> Dynamic Memory Management in C ++ hold an object of type type Constructs objects in already allocated storage Placement new 345 • Syntax: new ( placement_params ) type initializer • placement_params must be a pointer to a region of storage large enough to • The strict aliasing rule must not be violated • Alignment must be ensured manually • Only rarely required (e.g. for custom memory management)

  14. Dynamic Memory Management // lifetime of a1 begins, storage begins } // lifetime of a2 ends, storage ends delete a2; // lifetime of a2 begins A* a2 = new (a1) A(); // lifetime of a1 ends a1->~A(); A* a1 = new A(); Dynamic Memory Management in C ++ int main() { struct A { }; Example The lifetime of an object is equal to or nested within the lifetime of its storage Lifetimes and Storage Duration 346 • Equal for regular new and delete • Possibly nested for placement new

  15. Dynamic Memory Management Memory Manipulation Primitives std::memcpy (1) std::memcpy copies bytes between non-overlapping memory regions to by dest behavior Restrictions (undefjned behavior if violated) 347 • Defjned in <cstring> standard header • Syntax: void* memcpy(void* dest, const void* src, std::size_t count); • Copies count bytes from the object pointed to by src to the object pointed • Can be used to work around strict aliasing rules without causing undefjned • Objects must not overlap • src and dest must not be nullptr • Objects must be trivially copyable • dest must be aligned suitably

  16. Dynamic Memory Management Example (work around strict aliasing) } std::memcpy(&j, &i, sizeof(double)); // OK double j; int64_t i = 42; int main() { #include <cstdint> #include <cstring> } Memory Manipulation Primitives std::memcpy(&buffer[4], &buffer[0], 4 * sizeof(int)); buffer.resize(8); std::vector<int> buffer = {1, 2, 3, 4}; int main() { #include <vector> #include <cstring> Example (straightforward copy) std::memcpy (2) 348

  17. Dynamic Memory Management Memory Manipulation Primitives std::memmove (1) std::memmove copies bytes between possibly overlapping memory regions to by dest Restrictions (undefjned behavior if violated) 349 • Defjned in <cstring> standard header • Syntax: void* memmove(void* dest, const void* src, std::size_t count); • Copies count bytes from the object pointed to by src to the object pointed • Acts as if the bytes were copied to a temporary bufger • src and dest must not be nullptr • Objects must be trivially copyable • dest must be suitably aligned

  18. Dynamic Memory Management Memory Manipulation Primitives std::memmove (2) Example (straightforward copy) #include <cstring> #include <vector> int main() { std::vector<int> buffer = {1, 2, 3, 4}; buffer.resize(6); std::memmove(&buffer[2], &buffer[0], 4 * sizeof(int)); // buffer is now {1, 2, 1, 2, 3, 4} } 350

  19. Copy and Move Semantics Copy and Move Semantics 351

  20. Copy and Move Semantics Copy Semantics Copy Semantics Assignment and construction of classes employs copy semantics in most cases Considerations for user-defjned class types resources 352 • By default, a shallow copy is created • Usually not particularly relevant for fundamental types • Very relevant for user-defjned class types • Copying may be expensive • Copying may be unnecessary or even unwanted • An object on the left-hand side of an assignment might manage dynamic

Recommend


More recommend