Update
This commit is contained in:
parent
124b9d1e7c
commit
3f374a4713
85 changed files with 2281 additions and 2272 deletions
|
@ -20,7 +20,7 @@ For start let's see which kinds of allocation (and their associated parts of mem
|
|||
- **local variables** (including function arguments and local **variable size arrays**)
|
||||
- **dynamic allocation (heap memory)**: A kind of more complex manual allocation that happens at run time and is initiated by the programmer calling special functions such as `malloc` from the `stdlib` standard library, which return [pointers](pointer.md) to the allocated memory. This memory is taken from a special part of memory known as **[heap](heap.md)**. This allows to allocate, resize and deallocate potentially very big parts of memory, but requires caution as working with pointers is involved and there is a danger of **memory leaks** -- it is the responsibility of the programmer to free allocated memory with the `free` function once it is no longer needed, otherwise that memory will simply remain allocated and unusable by others (if this happens for example in a loop, the program may just start eating up more and more RAM and eventually run out of memory). Dynamic allocation is also pretty complex (it usually involves communicating with operating system and also keeping track of the structure of memory) and creates a [dependency](dependency.md) on the `stdlib` library. Some implementations of the allocation functions are also infamously slow (up to the point of some programmers resorting to program their own dynamic allocation systems). Therefore only use dynamic allocation when absolutely necessary! Dynamic allocation applies to:
|
||||
- **memory allocated with special functions** (`malloc`, `calloc`, `realloc`)
|
||||
|
||||
|
||||
Rule of the thumb: use the simplest thing possible, i.e. static allocation if you can, if not then automatic and only as the last option resort to dynamic allocation. The good news is that **you mostly won't need dynamic allocation** -- you basically only need it when working with data whose size can potentially be VERY big and is unknown at compile time (e.g. you need to load a WHOLE file AT ONCE which may potentially be VERY big). In other cases you can get away with static allocation (just reserving some reasonable amount of memory in advance and hope the data fits, e.g. a global array such as `int myData[DATA_MAX_SIZE]`) or automatic allocation if the data is reasonably small (i.e. you just create a variable sized array inside some function that processes the data). If you end up doing dynamic allocation, be careful, but it's not THAT hard to do it right (just pay more attention) and there are tools (e.g. [valgrind](valgrind.md)) to help you find memory leaks. However by the principles of [good design](lrs.md) **you should avoid dynamic allocation** if you can, not only because of the potential for errors and worse performance, but most importantly to avoid dependencies and complexity.
|
||||
|
||||
For [pros](pro.md): you can also create your own kind of pseudo dynamic allocation in pure C if you really want to avoid using stdlib or can't use it for some reason. The idea is to allocate a big chunk of memory statically (e.g. global `unsigned char myHeap[MY_HEAP_SIZE];`) and then create functions for allocating and freeing blocks of this static memory (e.g. `myAlloc` and `myFree` with same signatures as `malloc` and `free`). This allows you to use memory more efficiently than if you just dumbly (is it a word?) preallocate everything statically, i.e. you may need less total memory; this may be useful e.g. on [embedded](embedded.md). Yet another uber [hack](hacking.md) to "improve" this may be to allocate the "personal heap" on the stack instead of statically, i.e. you create something like a global pointer `unsigned char *myHeapPointer;` and a global variable `unsigned int myHeapSize;`, then somewhere at the beginning of `main` you compute the size `myHeapSize` and then create a local array `myHeap[myHeapSize]`, then finally set the global pointer to it as `myHeapPointer = myHeap`; the rest remains the same (your allocation function will access the heap via the global pointer). Just watch out for reinventing wheels, bugs and that you actually don't end up with a worse mess that if you took a more simple approach. Hell, you might even try to write your own garbage collection and array bound checking and whatnot, but then why just not fuck it and use an already existing abomination like [Java](java.md)? :)
|
||||
|
@ -51,7 +51,7 @@ void myFunction(int x)
|
|||
|
||||
int main(void)
|
||||
{
|
||||
int localNumberInMain = 123; // this is also allocated on stack
|
||||
int localNumberInMain = 123; // this is also allocated on stack
|
||||
|
||||
myFunction(10); // change to 10000000 to see a probable stack overflow
|
||||
|
||||
|
@ -70,9 +70,9 @@ int main(void)
|
|||
|
||||
dynamicMemory[i * 128] = 123; // do something with the memory
|
||||
|
||||
free(dynamicMemory); // if not done, memory leak occurs! try to remove this and see :)
|
||||
free(dynamicMemory); // if not done, memory leak occurs! try to remove this and see :)
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
```
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue