每天推薦一個 GitHub 優質開源項目和一篇精選英文科技或編程文章原文,歡迎關注開源日報。交流QQ群:202790710;微博:https://weibo.com/openingsource;電報群 https://t.me/OpeningSourceOrg

1


今日推薦開源項目:《藍貓淘氣五百問 DeepLearning-500-questions》傳送門:GitHub鏈接

推薦理由:對深度學習有些不懂的地方想要提問?這個項目就是對深度學習進行了介紹——以各種問題的形式。通過對各種不同的問題進行解答來讓閱讀者了解深度學習的相關內容,從最簡單的各種基礎到現在流行的 NLP(雖然還在完善中)都有涉及,興許你在尋找相關問題的時候,可能會大吃一驚:「這個問題剛好是我想問的,驚了!」


今日推薦英文原文:《Understand your program』s memory》作者:Tiago Antunes

原文鏈接:https://medium.com/@tm.antunes/understand-your-programs-memory-92431fa8c6b

推薦理由:了解你的程序的內存,如果你第一門編程語言選了個 C 或者 C++ 的話你大概已經被內存問題針對過好幾次了,這篇文章就介紹了應用程序是如何分配內存的,主要是介紹堆棧和堆,興許能夠減少你再次被這種問題所煩擾的機率

Understand your program』s memory

When coding in a language like C or C++ where you can interact with your memory in a more low-level way, sometimes it creates a lot of problems you didn』t get before: segfaults. These errors are rather annoying, and can cause you a lot of trouble and are often indicators that you』re using memory you shouldn』t use.

One of the most common problems is accessing memory that has already been free』d — memory that you』ve either released with free or memory that your program has automatically released (from the stack for example).

Understanding all this is really simple and it will definitely make you program better and in a smarter way.

How is the memory divided

High stands for high addresses

Memory is divided in multiple segments, two of the most important ones (for this post) are the stack and heap. The stack is an ordered insertion place while the heap is all random — you allocate memory wherever you can.

Stack memory has a set of ways and operations for its work (it』s where some of your processor』s registers information gets saved) and it』s where relevant information about your program goes — which functions are called, what variables you created, and some more information. This memory is also managed by the program and NOT by the developer.

The heap is often used to allocate big amounts of memory that is supposed to exist as long as the developer wants. That said, it』s the developer』s job to control the usage of the memory on the heap. When building complex programs, you often need to allocate big chunks of memory, and that』s where you use the heap. We call this Dynamic Memory.

You』re placing things on the Heap every time you use malloc to allocate memory for something. Any other call that goes like int i; is stack memory. Knowing this is really important so that you can easily find errors in your program and futher improve your Segfault error search!

Understanding the stack

Although you don』t know about it, your program is constantly allocating stack memory for it to work. Every local variable and every function you call goes there. With this, you can do a lot of things — most of them are things that you did not want to happen — like buffer overflows, accessing incorrect memory, etc.

So how does it really work?
The stack is a LIFO (Last-In-First-Out) data structure, which you can image as a box of perfectly fitted books — the last book you place is the first one you take out. By using this structure, the program can easily manage all its operations and scopes by using 2 simple operations: push and pop. These 2 do exactly the opposite of each other: push inserts the value to the top of the stack while pop takes the top value from it.

Push and Pop operations

To keep track of the current memory place, there is a special processor register called Stack Pointer. Every time you need to save something (a variable or the return address from a function), it pushes and moves the stack pointer up. Every time you exit from a function, it pops everything from the stack pointer until the saved return address from the function. It』s simple!

To test if you understood, let』s use the following example (try and find the bug alone ☺️):

Everything looks ok — until you run it

If you run it, the program will simply segfault. Why does this happen? Everything looks in place! Except about… the stack.

When we call the function createArray the stack saves the return address, creates arr in stack memory and returns it (an array is simply a pointer to a memory location with its information) but since we didn』t use malloc it gets saved in stack memory. After we return the pointer, since we don』t have any control over stack operations, the program pops the info from the stack and uses it as it needs. When we try to fill in the array after we returned from the function, we corrupt the memory — making the program segfault.

Understanding the heap

In opposition to the stack, the heap is what you use when you want to something to exist for some time independently of functions and scopes. To use this memory, C language stdlib is really good as it brings two awesome functions: malloc and free .

Malloc (memory allocation) requests the system for the amount of memory that was asked for, and returns a pointer to the starting address. Free tells the system that the memory we asked for is no longer needed and can be used for other tasks. Looks really simple — as long as you avoid mistakes.

Since the system can』t overwrite what develpers asked for, it depends on us, humans, to manage it with the 2 functions above. This opens the door for one human error: Memory Leaks.

Memory Leak is memory that was requested by the user that was never free』d when the program ended or that pointers to its locations were lost, making the program use much more memory than what it was supposed to. To avoid this, every time we don』t need an heap allocated element anymore, we free it.

Pointers: bad vs good

In the picture above, in the bad way never free the memory we used. This ends up in wasting 20 * 4 bytes (int size in 64-bit) = 80 bytes. This might not look that much, but imagine not doing this in a giant program. We can end up wasting gigabytes!

Managing your heap memory is essential to make your programs be memory efficient. But you also need to be careful on how you use it. Just like in stack memory, after the memory is free』d, accessing it or using it might cause you a segfault.

Bonus: Structs and the heap

One of the common mistakes when using structs is to just free the struct — which is fine, as long as we didn』t allocate memory to pointers inside the struct. If memory is allocated to pointers inside the struct, we need to first free them and only after free the entire struct.

Look at how I used free

How I solve my memory leaks problems

Most of the time I program in C I』m using structs, therefore I always have 2 mandatory functions to use with my structs: the constructor, and the destructor. These 2 functions are the only ones where I use mallocs and frees on the struct, making it really simple and easy to solve my memory leaks (If you would like to know more about making code easier to read, check my post on abstraction).

A way to create, and a way to destroy!

Don』t forget to follow me!

Besides posting here on Medium, I』m also on Twitter.

If you have any questions or suggestions, don』t hesitate to contact me!


每天推薦一個 GitHub 優質開源項目和一篇精選英文科技或編程文章原文,歡迎關注開源日報。交流QQ群:202790710;微博:https://weibo.com/openingsource;電報群 https://t.me/OpeningSourceOrg