{"id":203,"date":"2024-01-30T14:15:00","date_gmt":"2024-01-30T17:15:00","guid":{"rendered":"https:\/\/suspensao.blog.br\/disbelief\/?p=203"},"modified":"2024-01-24T17:35:37","modified_gmt":"2024-01-24T20:35:37","slug":"implementing-malloc-and-free-adding-metadata-to-the-memory-blocks","status":"publish","type":"post","link":"https:\/\/suspensao.blog.br\/disbelief\/implementing-malloc-and-free-adding-metadata-to-the-memory-blocks\/","title":{"rendered":"Implementing malloc() and free() \u2014 adding metadata to the memory blocks"},"content":{"rendered":"\n<p>This post is part of a series on implementing the <code>malloc()<\/code> and <code>free()<\/code> functions. Previously, <a href=\"https:\/\/suspensao.blog.br\/disbelief\/implementing-malloc-and-free-1\">we implemented a rather simplistic approach<\/a> that almost doesn&#8217;t free any memory: a pointer points to the last allocated block, enabling <code>free()<\/code> to deallocate it, but only it.<\/p>\n\n\n\n<p>A better option is to make the last block point to the second-to-last, the second-to-last block to the third-to-last, and so on, forming a <a href=\"https:\/\/en.wikipedia.org\/wiki\/Linked_list\">linked list<\/a>. To achieve this, we create a struct that will serve as the header of the blocks, containing a pointer to the previous block:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>typedef struct Header {\n  struct Header *previous;\n} Header;<\/code><\/pre>\n\n\n\n<p>Additionally, the pointer to the last block, which used to be <code>void*<\/code>, is now of type <code>Header*<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>Header *last = NULL;<\/code><\/pre>\n\n\n\n<p>To use these headers, <code>abmalloc()<\/code> reserves enough memory to store both the header and the requested size:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>void *abmalloc(size_t size) {\n  Header *header = sbrk(sizeof(Header) + size);<\/code><\/pre>\n\n\n\n<p>In this way, we use the beginning of the block to store necessary information, such as a pointer to the last allocated block before the new one:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  header-&gt;previous = last;<\/code><\/pre>\n\n\n\n<p>Then, we update <code>last<\/code> to point to the new block:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  last = header;<\/code><\/pre>\n\n\n\n<p>Finally, we return a pointer to the memory that the user can use. Since <code>header<\/code> points to the metadata, we cannot simply return it. Otherwise, all header information would be overwritten when the user used the pointer! Instead, we return a pointer to just after the header. This pointer is easy to calculate: it is the memory address of the header <em>plus<\/em> the size of the header:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  return header + 1;\n}<\/code><\/pre>\n\n\n\n<p>Note how we increment the <code>header<\/code> pointer by 1. Since the pointer type is <code>Header*<\/code>, the increment is actually the number of bytes of the <code>Header<\/code> struct, not just one byte. The type of the pointer is very relevant in <a href=\"https:\/\/www-ime-usp-br.translate.goog\/~pf\/algoritmos\/aulas\/pont.html?_x_tr_sl=pt&amp;_x_tr_tl=en&amp;_x_tr_hl=pt-BR&amp;_x_tr_pto=wapp#array\">pointer arithmetic<\/a>.<\/p>\n\n\n\n<p>Now that our memory blocks have metadata at the beginning, we need to take this into account when deallocating. <code>free()<\/code> receives a pointer not to the start of the block but to the memory made available to the user. Therefore, we need to find the start of the block from the pointer the user passed. Nothing that a little pointer arithmetic can&#8217;t solve:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>void abfree(void *ptr) {\n  Header *header = (Header*) ptr - 1;<\/code><\/pre>\n\n\n\n<p>If <code>header<\/code> points to the last allocated block, the previous block will become the last. In this case, we can return memory from the heap to the operating system through <code>brk()<\/code>:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>  if (header == last) {\n    last = header-&gt;previous;\n    brk(header);\n  }\n}<\/code><\/pre>\n\n\n\n<p>Here are our new <code>malloc()<\/code> and <code>free()<\/code> functions:<\/p>\n\n\n\n<pre class=\"wp-block-code\"><code>typedef struct Header {\n   struct Header *previous;\n } Header;\n\n Header *last = NULL;\n\n void *abmalloc(size_t size) {\n   Header *header = sbrk(sizeof(Header) + size);\n   header-&gt;previous = last;\n   last = header;\n   return header + 1;\n }\n\n void abfree(void *ptr) {\n   Header *header = (Header*) ptr - 1;\n   if (header == last) {\n     last = header-&gt;previous;\n     brk(header);\n   }\n }<\/code><\/pre>\n\n\n\n<p><code>abmalloc()<\/code> and <code>abfree()<\/code> may be slightly more memory-efficient now, but not by much. Dynamically allocated memory rarely behaves like a stack, where the oldest block is always deallocated first. In the next post, we will see how to use the memory of older blocks that are no longer in use.<\/p>\n\n\n\n<p><em>(This post is a translation of <a href=\"https:\/\/suspensao.blog.br\/descrenca\/implementando-malloc-e-free-adicionando-metadados-aos-blocos-de-memoria\/\">Implementando malloc() e free() \u2014 adicionando metadados aos blocos de mem\u00f3ria<\/a>, from <a href=\"https:\/\/suspensao.blog.br\/descrenca\">Suspens\u00e3o de Descren\u00e7a<\/a>.)<\/em><\/p>\n","protected":false},"excerpt":{"rendered":"<p>When malloc() reserves blocks of memory, it needs to somehow make it able to unreserve them later, when free() is called. We fall short of any real solution for this in our last post. In this post, though, we take the first, most fundamental steps to bring real memory efficient to our implementations of malloc() and free()!<\/p>\n","protected":false},"author":1,"featured_media":204,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_jetpack_newsletter_access":"","_jetpack_dont_email_post_to_subs":false,"_jetpack_newsletter_tier_id":0,"_jetpack_memberships_contains_paywalled_content":false,"_jetpack_feature_clip_id":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":"","jetpack_publicize_message":"","jetpack_publicize_feature_enabled":true,"jetpack_social_post_already_shared":true,"jetpack_social_options":{"image_generator_settings":{"template":"highway","default_image_id":0,"font":"","enabled":false},"version":2},"jetpack_post_was_ever_published":false},"categories":[75,76,6],"tags":[77,82,80,78,47],"class_list":["post-203","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-c","category-linux","category-programming","tag-c","tag-linux","tag-malloc","tag-memory-management","tag-software-development"],"jetpack_publicize_connections":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/suspensao.blog.br\/disbelief\/wp-content\/uploads\/2024\/01\/Metal_chain_Unsplash.jpg?fit=1024%2C685&ssl=1","jetpack_sharing_enabled":true,"jetpack_shortlink":"https:\/\/wp.me\/p9Ru6q-3h","jetpack-related-posts":[],"_links":{"self":[{"href":"https:\/\/suspensao.blog.br\/disbelief\/wp-json\/wp\/v2\/posts\/203","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/suspensao.blog.br\/disbelief\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/suspensao.blog.br\/disbelief\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/suspensao.blog.br\/disbelief\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/suspensao.blog.br\/disbelief\/wp-json\/wp\/v2\/comments?post=203"}],"version-history":[{"count":4,"href":"https:\/\/suspensao.blog.br\/disbelief\/wp-json\/wp\/v2\/posts\/203\/revisions"}],"predecessor-version":[{"id":209,"href":"https:\/\/suspensao.blog.br\/disbelief\/wp-json\/wp\/v2\/posts\/203\/revisions\/209"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/suspensao.blog.br\/disbelief\/wp-json\/wp\/v2\/media\/204"}],"wp:attachment":[{"href":"https:\/\/suspensao.blog.br\/disbelief\/wp-json\/wp\/v2\/media?parent=203"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/suspensao.blog.br\/disbelief\/wp-json\/wp\/v2\/categories?post=203"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/suspensao.blog.br\/disbelief\/wp-json\/wp\/v2\/tags?post=203"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}