Dynamic vs Static memory allocation

There is a structure:

typedef struct Point
{
   int x;
   int y;
} point_t;

What is the best way to create an" instance " of the structure?

  1. Way:

     point_t p;
    
  2. Way:

     point_t* p = new point_t();
    

The 1 way is preferable because of the speed, but not infrequently I see the 2 way. So what's the difference (other than being able to do delete whenever you want)?

Author: 0xdb, 2019-09-04

1 answers

The difference is in the way the data is stored.


In the first case, the variables are stored in the stack of the program. It follows from this:

  1. Limited scope and lifetime.

  2. When you exit the scope, the stored variables are automatically destroyed.

  3. Faster memory allocation/deallocation speed.


In the second case, the variables are stored in theheap . Heap slower stack allocates and frees resources, does not automatically clean up (at least in standard C++), is prone to fragmentation. However, it has some special features:

  1. The lifetime of a variable is not limited by the execution process. Without an explicit call to delete, the variable will exist until the end of the program execution.

  2. Knowing the address of a variable in the heap, it can be accessed from any scope.

  3. A heap in a sense "rubber". Unlike the stack, it is only physically limited.


As a result, creating on the stack should be used in cases where the variable is small or of acceptable size, or is used only here and nowhere else.

If a variable is to be used during the life of the entire program, access to it is needed at any time, its creation / copying takes a lot of time/memory, or it is not known in advance how much memory is needed, that is it makes more sense to use a heap (create once and then use a ready-made instance from the heap, rather than create and initialize an analog in the stack each time).

However, when working with a heap, you need to be careful. Errors when working with dynamic memory are fraught with memory leaks and sigsegv-s.

I advise you to read more about the representation of the heap and stack. There are links to useful information.

UPD: Regarding the speed of working with the heap, I bring the exhaust disassembler of Qt 5.13 (MinGW 7.3.0):

        3 [1]   {
0x401560                  55                    push   %rbp
0x401561  <+    1>        48 89 e5              mov    %rsp,%rbp
0x401564  <+    4>        48 83 ec 30           sub    $0x30,%rsp
0x401568  <+    8>        e8 f3 00 00 00        callq  0x401660 <__main>
        4 [1]       int a = 10;
0x40156d  <+   13>        c7 45 fc 0a 00 00 00  movl   $0xa,-0x4(%rbp)
        6 [1]       int *b = new int{10};
0x401574  <+   20>        b9 04 00 00 00        mov    $0x4,%ecx
0x401579  <+   25>        e8 22 00 00 00        callq  0x4015a0 <_Znwy>
0x40157e  <+   30>        c7 00 0a 00 00 00     movl   $0xa,(%rax)
0x401584  <+   36>        48 89 45 f0           mov    %rax,-0x10(%rbp)
        7 [1]       delete b;
0x401588  <+   40>        48 8b 45 f0           mov    -0x10(%rbp),%rax
0x40158c  <+   44>        48 89 c1              mov    %rax,%rcx
0x40158f  <+   47>        e8 14 00 00 00        callq  0x4015a8 <_ZdlPv>
        9 [1]       return 1;
0x401594  <+   52>        b8 01 00 00 00        mov    $0x1,%eax
        10 [1]  }
0x401599  <+   57>        48 83 c4 30           add    $0x30,%rsp
0x40159d  <+   61>        5d                    pop    %rbp
0x40159e  <+   62>        c3                    retq

You can see that when working with dynamic memory, there are additional instructions plus a procedure call. Plus, synchronization issues are added to the heap in multithreaded applications (this is of course quite a secondary point, but it also has a place to be)

P.S. if I forgot something, I will be grateful for the additions.

 4
Author: Bogdan, 2019-09-05 05:02:51