Implementando malloc() e free() — juntando blocos pequenos

You are viewing an old revision of this post, from January 19, 2025 @ 18:16:23. See below for differences between this version and the current revision.

No post anterior, aprendemos como dividir blocos para aproveitar melhor os espaços grandes. Contudo, isso traz um novo desafio: a fragmentação da memória. Blocos ores podem se acumular, formando cadeias de blocos livres que, se unificados, atenderiam a requisições maiores. À medida que os blocos são divididos, tornam-se cada vez menores, dificultando seu reaproveitamento.

Como blocos pequenos podem aumentar o consumo de memória

Considere, por exemplo, o snippet de código abaixo:

void *ptr1 = abmalloc(128);
void *ptr2 = abmalloc(8);
abfree(ptr1);
void *ptr3 = abmalloc(8);
abfree(ptr3);
void *ptr4 = abmalloc(128);Code language: JavaScript (javascript)

Nele, alocamos 128 bytes de memória e, posteriormente, 8 bytes. Os blocos de memória teriam um layout similar à figura abaixo:

Diagrama mostrando o resultado das operações de alocação - um bloco de memória largo e em uso, seguido de um pequeno também em uso

Depois, liberamos o bloco maior:

Diagrama mostrando o resultado da primeira chamada de abfree() - um bloco de memória largo e livre para ser reutilizado, seguido de um pequeno ainda ocupado

…e alocamos 8 bytes. Devido às últimas mudanças na função abmalloc(), esses 8 bytes serão extraídos do bloco maior:

Diagrama mostrando o resultado das operações de alocação após liberar 128 bytes - um bloco de memória largo e livre, seguido dois blocos pequenos também em uso

Agora, ao liberar os 8 bytes recém-alocados, obtivemos dois blocos livres:

Diagrama mostrando mm bloco de memória largo e livre, seguido de um bloco pequeno livre e um bloco pequeno em uso

Quando alocamos um novo bloco de 128 bytes, enfrentamos um problema: nenhum dos dois blocos livres possui tamanho suficiente individualmente, embora, juntos, eles pudessem atender à requisição. Como resultado, um novo bloco é alocado no final da stack, que continua a crescer.

Um bloco de memória largo e livre, um bloco pequeno e livre, um bloco pequeno ocupado e um bloco grande ocupado. Se o bloco menor que está livre agora não tivesse sido extraído do maior, poderíamos ter aproveitado o bloco maior livre.

Uma solução para esse problema é unir blocos livres adjacentes.

Refatorando para reuso e legibilidade

Antes de prosseguirmos, faremos mais uma rodada de refatorações, pois há trechos de código pequenos, mas complexos, que serão reutilizados.

Primeiramente, vamos criar uma função que, ao receber um header, retorne um ponteiro para a área de memória a ser devolvida ao usuário. Até agora, temos obtido esse resultado somando uma unidade ao ponteiro do header. Vamos encapsular essa lógica em uma função para simplificar e melhorar a reutilização do código:

void *header_user_area(Header *header) {
  return header + 1;
}Code language: JavaScript (javascript)

Consequentemente, em todos os lugares de abmalloc() onde anteriormente utilizávamos:

return header + 1;Code language: JavaScript (javascript)

…vamos utilizar a nova função:

return header_user_area(first);

Também precisamos frequentemente do ponteiro para a posição de memória após o bloco. Atualmente, calculamos isso com uma fórmula um tanto complicada: fazemos o casting do ponteiro do header para void*, somamos o tamanho da estrutura Header e adicionamos o tamanho do bloco alocado. Essa lógica pode ser observada na função header_split():

    Header *new_header = ((void*)header) + sizeof(Header) + header->size;Code language: JavaScript (javascript)

Vamos criar uma função para executar esta operação, chamada header_address_after_block():

void *header_address_after_block(Header *header) {<br>  return ((void*)header) + sizeof(Header) + header->size;<br>}Code language: JavaScript (javascript)

Como a função header_user_area() já realiza basicamente a mesma operação que a primeira parte da fórmula, podemos utilizá-la para simplificar header_split():

void *header_address_after_block(Header *header) {
  return header_user_area(header) + header->size;
}Code language: JavaScript (javascript)

Depois disso, substituiremos a fórmula pela nossa função em header_split():

    Header *new_header = header_address_after_block(header);

Por fim, será necessário verificar se, dado um header, existe um bloco livre antes ou depois dele. A expressão para essa verificação é intuitiva, mas extensa. Por exemplo, a fórmula abaixo é usada para determinar se há um bloco livre antes:

(header->previous != NULL) && header->previous->availableCode language: PHP (php)

Para facilitar um pouco a leitura, vamos colocar essa expressão em uma função, assim como a outra, correspondente a blocos posteriores:

bool header_previous_available(Header *header) {
  return (header->previous != NULL) && header->previous->available;
}

bool header_next_available(Header *header) {
  return (header->next != NULL) && header->next->available;
}Code language: PHP (php)

Pronto, agora temos quatro novas ferramentas que irão nos ajudar a fundir blocos disponíveis. Vamos em frente!

Procurando blocos livres adjacentes

Para juntar blocos de memória livres e adjacentes, precisamos, no momento da desalocação, verificar se o bloco anterior ou o bloco posterior estão disponíveis. Podemos fazer isso criando duas variáveis: uma para apontar para o primeiro bloco livre e outra para o último bloco livre. Inicialmente, ambas apontarão para o bloco que está sendo desalocado.

Header *header_merge(Header *header) {<br>  Header *first_available = header;<br>  Header *last_available = header;Code language: HTML, XML (xml)

Se o bloco anterior ao atual estiver livre, first_available aponta para ele.

   if (header_previous_available(header)) {<br>     first_available = header->previous;<br>   }Code language: HTML, XML (xml)

De modo análogo, se o próximo bloco estiver disponível, last_available deve apontar para ele

  if (header_next_available(header)) {<br>    last_available = header->next;<br>  }Code language: HTML, XML (xml)

Quando não há blocos livres

Caso não haja blocos livres nem à frente nem antes do bloco recém-desalocado, não há nada a ser fundido. Neste caso, as variáveis first_available e last_available serão iguais a header, e nossa função simplesmente retornará o ponteiro para o bloco que foi passado a ela.

  if ((first_available == header) && (last_available == header)) {
    return header;
  }Code language: JavaScript (javascript)

Nota: Não precisamos verificar o bloco anterior ao anterior, ou o posterior ao posterior, e assim por diante. Se, em cada chamada de abfree(), fundimos o bloco com qualquer vizinho livre, é impossível ter dois blocos livres consecutivos. Portanto, basta verificar apenas os vizinhos imediatos.

Atualizando o tamanho quando há blocos livres

Caso alguma das variáveis first_available ou last_available não seja igual a header, precisaremos fundir os blocos. Para isso, precisamos realizar duas ações.

Primeiro, devemos atualizar o tamanho do primeiro bloco disponível para incluir o último bloco. Para isso, obtemos o ponteiro que aponta logo após o último bloco disponível.

  void *end = header_address_after_block(last_available);Code language: JavaScript (javascript)

O tamanho do novo bloco será a diferença entre este ponteiro e o endereço do bloco de usuário:

  size_t size = end - header_user_area(first_available);E

Uma vez que tenhamos o tamanho, só precisamos atualizar o primeiro bloco disponível:

  header_init(first_available, size, true);Code language: JavaScript (javascript)

Atualizando ponteiros do bloco fundido

Com o tamanho do bloco atualizado, precisamos ajustar seus ponteiros. Para o ponteiro para trás, ele deve passar a apontar para o bloco anterior ao primeiro bloco disponível:

  Header *previous = first_available->previous;Code language: PHP (php)

Já o próximo deve ser o que se seguia ao último bloco disponível:

  Header *next = last_available->next;Code language: PHP (php)

Uma vez que tenhamos esses valores, basta conectá-los adequadamente utilizando a função header_plug():

  header_plug(first_available, previous, next);

Caso de borda: o último bloco

Um último cuidado que devemos ter é considerar que o novo bloco pode vir a ser o último. Neste caso, o bloco que criamos deve se tornar o último bloco agora.

  if (last_available == last) {<br>    last = first_available;<br>  }<br>  return first_available;<br>}Code language: HTML, XML (xml)

Com isso, nossa função de fusão está implementada.

Utilizando header_merge() em abfree()

Agora que temos uma função que une blocos livres, alteramos abfree() para invocá-la no header do bloco a ser desalocado. Feito isso, prosseguimos com a liberação de memória

  Header *header = (Header*) ptr - 1;
  header = header_merge(header);

  if (header == last) {

Conclusão

Aqui está a função abfree() completa:

void abfree(void *ptr) {
  if (ptr == NULL) {
    return;
  } 
  Header *header = (Header*) ptr - 1;

  header = header_merge(header);

  if (header == last) {
    while (header_previous_available(header)) {
      header = header->previous;
    } 
    last = header->previous;
    if (last != NULL) {
      last->next = NULL;
    } else {
      first = NULL;
    } 
    brk(header);
  } else {
    header->available = true;
  } 
} Code language: PHP (php)

Com as alterações deste e do último post, o tamanho dos blocos livres deixam de ser um agravante no consumo de memória, e nossa função malloc() aproxima-se de ficar pronta. Há porém, um último problema a ser resolvido: o alinhamento de blocos de memória. Examinaremos isto no próximo post.

Post Revisions:

Changes:

January 19, 2025 @ 18:16:23Current Revision
Content
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>No <a href="https:/ /suspensao.blog.br/descrenca/ implementando- malloc-e-free- dividindo-blocos-grandes/ "><em>post</em> anterior</a>, aprendemos como dividir blocos para aproveitar melhor os espaços grandes. Contudo, isso traz um novo desafio: a fragmentação da memória. Blocos ores podem se acumular, formando cadeias de blocos livres que, se unificados, atenderiam a requisições maiores. À medida que os blocos são divididos, tornam-se cada vez menores, dificultando seu reaproveitamento.</p>Unchanged: <p>No <a href="https:/ /suspensao.blog.br/descrenca/ implementando- malloc-e-free- dividindo-blocos-grandes/ "><em>post</em> anterior</a>, aprendemos como dividir blocos para aproveitar melhor os espaços grandes. Contudo, isso traz um novo desafio: a fragmentação da memória. Blocos ores podem se acumular, formando cadeias de blocos livres que, se unificados, atenderiam a requisições maiores. À medida que os blocos são divididos, tornam-se cada vez menores, dificultando seu reaproveitamento.</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:heading -->Unchanged: <!-- wp:heading -->
Unchanged: <h2 class="wp-block- heading">Como blocos pequenos podem aumentar o consumo de memória</h2>Unchanged: <h2 class="wp-block- heading">Como blocos pequenos podem aumentar o consumo de memória</h2>
Unchanged: <!-- /wp:heading -->Unchanged: <!-- /wp:heading -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>Considere, por exemplo, o <em>snippet</em> de código abaixo:</p>Unchanged: <p>Considere, por exemplo, o <em>snippet</em> de código abaixo:</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:code -->Unchanged: <!-- wp:code -->
Unchanged: <pre class="wp-block- code"><code>void *ptr1 = abmalloc(128);Unchanged: <pre class="wp-block- code"><code>void *ptr1 = abmalloc(128);
Unchanged: void *ptr2 = abmalloc(8);Unchanged: void *ptr2 = abmalloc(8);
Unchanged: abfree(ptr1);Unchanged: abfree(ptr1);
Unchanged: void *ptr3 = abmalloc(8);Unchanged: void *ptr3 = abmalloc(8);
Unchanged: abfree(ptr3);Unchanged: abfree(ptr3);
Unchanged: void *ptr4 = abmalloc(128) ;</code></pre>Unchanged: void *ptr4 = abmalloc(128) ;</code></pre>
Unchanged: <!-- /wp:code -->Unchanged: <!-- /wp:code -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>Nele, alocamos 128 bytes de memória e, posteriormente, 8 bytes. Os blocos de memória teriam um <em>layout</em> similar à figura abaixo:</p>Unchanged: <p>Nele, alocamos 128 bytes de memória e, posteriormente, 8 bytes. Os blocos de memória teriam um <em>layout</em> similar à figura abaixo:</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:image {"id":680,"sizeSlug" :"full","linkDestination":"media"} -->Unchanged: <!-- wp:image {"id":680,"sizeSlug" :"full","linkDestination":"media"} -->
Unchanged: <figure class="wp-block-image size-full"><a href="https:/ /suspensao.blog.br/descrenca/ wp-content/uploads/2025/01/ bloco-grande- ocupado-bloco- pequeno-ocupado.png"><img src="https:// suspensao.blog.br/descrenca/ wp-content/uploads/2025/01/ bloco-grande- ocupado-bloco- pequeno-ocupado.png" alt="Diagrama mostrando o resultado das operações de alocação - um bloco de memória largo e em uso, seguido de um pequeno também em uso" class="wp-image- 680"/></a></figure>Unchanged: <figure class="wp-block-image size-full"><a href="https:/ /suspensao.blog.br/descrenca/ wp-content/uploads/2025/01/ bloco-grande- ocupado-bloco- pequeno-ocupado.png"><img src="https:// suspensao.blog.br/descrenca/ wp-content/uploads/2025/01/ bloco-grande- ocupado-bloco- pequeno-ocupado.png" alt="Diagrama mostrando o resultado das operações de alocação - um bloco de memória largo e em uso, seguido de um pequeno também em uso" class="wp-image- 680"/></a></figure>
Unchanged: <!-- /wp:image -->Unchanged: <!-- /wp:image -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>Depois, liberamos o bloco maior:</p>Unchanged: <p>Depois, liberamos o bloco maior:</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:image {"id":681,"sizeSlug" :"full","linkDestination":"media"} -->Unchanged: <!-- wp:image {"id":681,"sizeSlug" :"full","linkDestination":"media"} -->
Unchanged: <figure class="wp-block-image size-full"><a href="https:/ /suspensao.blog.br/descrenca/ wp-content/uploads/2025/01/ bloco-grande- livre-bloco- pequeno-ocupado.png"><img src="https:// suspensao.blog.br/descrenca/ wp-content/uploads/2025/01/ bloco-grande- livre-bloco- pequeno-ocupado.png" alt="Diagrama mostrando o resultado da primeira chamada de abfree() - um bloco de memória largo e livre para ser reutilizado, seguido de um pequeno ainda ocupado" class="wp-image- 681"/></a></figure>Unchanged: <figure class="wp-block-image size-full"><a href="https:/ /suspensao.blog.br/descrenca/ wp-content/uploads/2025/01/ bloco-grande- livre-bloco- pequeno-ocupado.png"><img src="https:// suspensao.blog.br/descrenca/ wp-content/uploads/2025/01/ bloco-grande- livre-bloco- pequeno-ocupado.png" alt="Diagrama mostrando o resultado da primeira chamada de abfree() - um bloco de memória largo e livre para ser reutilizado, seguido de um pequeno ainda ocupado" class="wp-image- 681"/></a></figure>
Unchanged: <!-- /wp:image -->Unchanged: <!-- /wp:image -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>...e alocamos 8 bytes. Devido às <a href="https:/ /suspensao.blog.br/descrenca/ implementando- malloc-e-free- dividindo-blocos- grandes/">últimas mudanças na função <code>abmalloc( )</code></a>, esses 8 bytes serão extraídos do bloco maior:</p>Unchanged: <p>...e alocamos 8 bytes. Devido às <a href="https:/ /suspensao.blog.br/descrenca/ implementando- malloc-e-free- dividindo-blocos- grandes/">últimas mudanças na função <code>abmalloc( )</code></a>, esses 8 bytes serão extraídos do bloco maior:</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:image {"id":682,"sizeSlug" :"full","linkDestination":"media"} -->Unchanged: <!-- wp:image {"id":682,"sizeSlug" :"full","linkDestination":"media"} -->
Unchanged: <figure class="wp-block-image size-full"><a href="https:/ /suspensao.blog.br/descrenca/ wp-content/uploads/2025/01/ bloco-grande- livre-bloco- pequeno-ocupado- bloco-pequeno- ocupado.png"><img src="https:// suspensao.blog.br/descrenca/ wp-content/uploads/2025/01/ bloco-grande- livre-bloco- pequeno-ocupado- bloco-pequeno- ocupado.png" alt="Diagrama mostrando o resultado das operações de alocação após liberar 128 bytes - um bloco de memória largo e livre, seguido dois blocos pequenos também em uso" class="wp-image- 682"/></a></figure>Unchanged: <figure class="wp-block-image size-full"><a href="https:/ /suspensao.blog.br/descrenca/ wp-content/uploads/2025/01/ bloco-grande- livre-bloco- pequeno-ocupado- bloco-pequeno- ocupado.png"><img src="https:// suspensao.blog.br/descrenca/ wp-content/uploads/2025/01/ bloco-grande- livre-bloco- pequeno-ocupado- bloco-pequeno- ocupado.png" alt="Diagrama mostrando o resultado das operações de alocação após liberar 128 bytes - um bloco de memória largo e livre, seguido dois blocos pequenos também em uso" class="wp-image- 682"/></a></figure>
Unchanged: <!-- /wp:image -->Unchanged: <!-- /wp:image -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>Agora, ao liberar os 8 bytes recém-alocados, obtivemos dois blocos livres:</p>Unchanged: <p>Agora, ao liberar os 8 bytes recém-alocados, obtivemos dois blocos livres:</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:image {"id":683,"sizeSlug" :"full","linkDestination":"media"} -->Unchanged: <!-- wp:image {"id":683,"sizeSlug" :"full","linkDestination":"media"} -->
Unchanged: <figure class="wp-block-image size-full"><a href="https:/ /suspensao.blog.br/descrenca/ wp-content/uploads/2025/01/ bloco-grande- livre-bloco- pequeno-livre- bloco-pequeno- ocupado.png"><img src="https:// suspensao.blog.br/descrenca/ wp-content/uploads/2025/01/ bloco-grande- livre-bloco- pequeno-livre- bloco-pequeno- ocupado.png" alt="Diagrama mostrando mm bloco de memória largo e livre, seguido de um bloco pequeno livre e um bloco pequeno em uso" class="wp-image- 683"/></a></figure>Unchanged: <figure class="wp-block-image size-full"><a href="https:/ /suspensao.blog.br/descrenca/ wp-content/uploads/2025/01/ bloco-grande- livre-bloco- pequeno-livre- bloco-pequeno- ocupado.png"><img src="https:// suspensao.blog.br/descrenca/ wp-content/uploads/2025/01/ bloco-grande- livre-bloco- pequeno-livre- bloco-pequeno- ocupado.png" alt="Diagrama mostrando mm bloco de memória largo e livre, seguido de um bloco pequeno livre e um bloco pequeno em uso" class="wp-image- 683"/></a></figure>
Unchanged: <!-- /wp:image -->Unchanged: <!-- /wp:image -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>Quando alocamos um novo bloco de 128 bytes, enfrentamos um problema: nenhum dos dois blocos livres possui tamanho suficiente individualmente, embora, juntos, eles pudessem atender à requisição. Como resultado, um novo bloco é alocado no final da <em>stack</em>, que continua a crescer.</p>Unchanged: <p>Quando alocamos um novo bloco de 128 bytes, enfrentamos um problema: nenhum dos dois blocos livres possui tamanho suficiente individualmente, embora, juntos, eles pudessem atender à requisição. Como resultado, um novo bloco é alocado no final da <em>stack</em>, que continua a crescer.</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:image {"id":684,"sizeSlug" :"large","linkDestination":"media"} -->Unchanged: <!-- wp:image {"id":684,"sizeSlug" :"large","linkDestination":"media"} -->
Unchanged: <figure class="wp-block-image size-large"><a href="https:/ /suspensao.blog.br/descrenca/ wp-content/uploads/2025/01/ bloco-grande- livre-bloco- pequeno-livre- bloco-pequeno- ocupado-bloco- grande-ocupado.png"><img src="https:// suspensao.blog.br/descrenca/ wp-content/uploads/2025/01/ bloco-grande- livre-bloco- pequeno-livre- bloco-pequeno- ocupado-bloco- grande-ocupado- 1024x39.png" alt="Um bloco de memória largo e livre, um bloco pequeno e livre, um bloco pequeno ocupado e um bloco grande ocupado. Se o bloco menor que está livre agora não tivesse sido extraído do maior, poderíamos ter aproveitado o bloco maior livre." class="wp-image- 684"/></a></figure>Unchanged: <figure class="wp-block-image size-large"><a href="https:/ /suspensao.blog.br/descrenca/ wp-content/uploads/2025/01/ bloco-grande- livre-bloco- pequeno-livre- bloco-pequeno- ocupado-bloco- grande-ocupado.png"><img src="https:// suspensao.blog.br/descrenca/ wp-content/uploads/2025/01/ bloco-grande- livre-bloco- pequeno-livre- bloco-pequeno- ocupado-bloco- grande-ocupado- 1024x39.png" alt="Um bloco de memória largo e livre, um bloco pequeno e livre, um bloco pequeno ocupado e um bloco grande ocupado. Se o bloco menor que está livre agora não tivesse sido extraído do maior, poderíamos ter aproveitado o bloco maior livre." class="wp-image- 684"/></a></figure>
Unchanged: <!-- /wp:image -->Unchanged: <!-- /wp:image -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>Uma solução para esse problema é unir blocos livres adjacentes.</p>Unchanged: <p>Uma solução para esse problema é unir blocos livres adjacentes.</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:heading -->Unchanged: <!-- wp:heading -->
Unchanged: <h2 class="wp-block- heading">Refatorando para reuso e legibilidade</h2>Unchanged: <h2 class="wp-block- heading">Refatorando para reuso e legibilidade</h2>
Unchanged: <!-- /wp:heading -->Unchanged: <!-- /wp:heading -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>Antes de prosseguirmos, faremos mais uma rodada de refatorações, pois há trechos de código pequenos, mas complexos, que serão reutilizados.</p>Unchanged: <p>Antes de prosseguirmos, faremos mais uma rodada de refatorações, pois há trechos de código pequenos, mas complexos, que serão reutilizados.</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>Primeiramente, vamos criar uma função que, ao receber um <em>header</em>, retorne um ponteiro para a área de memória a ser devolvida ao usuário. Até agora, temos obtido esse resultado somando uma unidade ao ponteiro do <em>header</em>. Vamos encapsular essa lógica em uma função para simplificar e melhorar a reutilização do código:</p>Unchanged: <p>Primeiramente, vamos criar uma função que, ao receber um <em>header</em>, retorne um ponteiro para a área de memória a ser devolvida ao usuário. Até agora, temos obtido esse resultado somando uma unidade ao ponteiro do <em>header</em>. Vamos encapsular essa lógica em uma função para simplificar e melhorar a reutilização do código:</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:code -->Unchanged: <!-- wp:code -->
Unchanged: <pre class="wp-block- code"><code>void *header_user_area(Header *header) {Unchanged: <pre class="wp-block- code"><code>void *header_user_area(Header *header) {
Unchanged: return header + 1;Unchanged: return header + 1;
Unchanged: }</code></pre>Unchanged: }</code></pre>
Unchanged: <!-- /wp:code -->Unchanged: <!-- /wp:code -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>Consequentemente, em todos os lugares de <code>abmalloc()</code> onde anteriormente utilizávamos:</p>Unchanged: <p>Consequentemente, em todos os lugares de <code>abmalloc()</code> onde anteriormente utilizávamos:</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:code -->Unchanged: <!-- wp:code -->
Unchanged: <pre class="wp-block- code"><code>return header + 1;</code></pre>Unchanged: <pre class="wp-block- code"><code>return header + 1;</code></pre>
Unchanged: <!-- /wp:code -->Unchanged: <!-- /wp:code -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>...vamos utilizar a nova função:</p>Unchanged: <p>...vamos utilizar a nova função:</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:preformatted -->Unchanged: <!-- wp:preformatted -->
Unchanged: <pre class="wp-block- preformatted">return header_user_area( first);</pre>Unchanged: <pre class="wp-block- preformatted">return header_user_area( first);</pre>
Unchanged: <!-- /wp:preformatted -->Unchanged: <!-- /wp:preformatted -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>Também precisamos frequentemente do ponteiro para a posição de memória após o bloco. Atualmente, calculamos isso com uma fórmula um tanto complicada: fazemos o casting do ponteiro do header para <code>void*</code>, somamos o tamanho da estrutura <code>Header</code> e adicionamos o tamanho do bloco alocado. Essa lógica pode ser observada na função <code>header_ split()</code>:</p>Unchanged: <p>Também precisamos frequentemente do ponteiro para a posição de memória após o bloco. Atualmente, calculamos isso com uma fórmula um tanto complicada: fazemos o casting do ponteiro do header para <code>void*</code>, somamos o tamanho da estrutura <code>Header</code> e adicionamos o tamanho do bloco alocado. Essa lógica pode ser observada na função <code>header_ split()</code>:</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:code -->Unchanged: <!-- wp:code -->
Unchanged: <pre class="wp-block- code"><code> Header *new_header = ((void*)header) + sizeof(Header) + header-&gt;size; </code></pre>Unchanged: <pre class="wp-block- code"><code> Header *new_header = ((void*)header) + sizeof(Header) + header-&gt;size; </code></pre>
Unchanged: <!-- /wp:code -->Unchanged: <!-- /wp:code -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>Vamos criar uma função para executar esta operação, chamada <code>header_ address_after_ block()</code>:</p>Unchanged: <p>Vamos criar uma função para executar esta operação, chamada <code>header_ address_after_ block()</code>:</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:code -->Unchanged: <!-- wp:code -->
Unchanged: <pre class="wp-block- code"><code>void *header_address_ after_block(Header *header) {<br> return ((void*)header) + sizeof(Header) + header-&gt;size; <br>}</code></pre>Unchanged: <pre class="wp-block- code"><code>void *header_address_ after_block(Header *header) {<br> return ((void*)header) + sizeof(Header) + header-&gt;size; <br>}</code></pre>
Unchanged: <!-- /wp:code -->Unchanged: <!-- /wp:code -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>Como a função <code>header_ user_area()</code> já realiza basicamente a mesma operação que a primeira parte da fórmula, podemos utilizá-la para simplificar <code>header_ split()</code>:</p>Unchanged: <p>Como a função <code>header_ user_area()</code> já realiza basicamente a mesma operação que a primeira parte da fórmula, podemos utilizá-la para simplificar <code>header_ split()</code>:</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:code -->Unchanged: <!-- wp:code -->
Unchanged: <pre class="wp-block- code"><code>void *header_address_ after_block(Header *header) {Unchanged: <pre class="wp-block- code"><code>void *header_address_ after_block(Header *header) {
Unchanged: return header_user_area(header) + header-&gt;size;Unchanged: return header_user_area(header) + header-&gt;size;
Unchanged: }</code></pre>Unchanged: }</code></pre>
Unchanged: <!-- /wp:code -->Unchanged: <!-- /wp:code -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>Depois disso, substituiremos a fórmula pela nossa função em <code>header_ split()</code>:</p>Unchanged: <p>Depois disso, substituiremos a fórmula pela nossa função em <code>header_ split()</code>:</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:code -->Unchanged: <!-- wp:code -->
Unchanged: <pre class="wp-block- code"><code> Header *new_header = header_address_ after_block(header) ;</code></pre>Unchanged: <pre class="wp-block- code"><code> Header *new_header = header_address_ after_block(header) ;</code></pre>
Unchanged: <!-- /wp:code -->Unchanged: <!-- /wp:code -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>Por fim, será necessário verificar se, dado um <code>header</code>, existe um bloco livre antes ou depois dele. A expressão para essa verificação é intuitiva, mas extensa. Por exemplo, a fórmula abaixo é usada para determinar se há um bloco livre antes:</p>Unchanged: <p>Por fim, será necessário verificar se, dado um <code>header</code>, existe um bloco livre antes ou depois dele. A expressão para essa verificação é intuitiva, mas extensa. Por exemplo, a fórmula abaixo é usada para determinar se há um bloco livre antes:</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:code -->Unchanged: <!-- wp:code -->
Unchanged: <pre class="wp-block- code"><code>( header-&gt;previous != NULL) &amp;&amp; header-&gt;previous- &gt;available< /code></pre>Unchanged: <pre class="wp-block- code"><code>( header-&gt;previous != NULL) &amp;&amp; header-&gt;previous- &gt;available< /code></pre>
Unchanged: <!-- /wp:code -->Unchanged: <!-- /wp:code -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>Para facilitar um pouco a leitura, vamos colocar essa expressão em uma função, assim como a outra, correspondente a blocos posteriores:</p>Unchanged: <p>Para facilitar um pouco a leitura, vamos colocar essa expressão em uma função, assim como a outra, correspondente a blocos posteriores:</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:code -->Unchanged: <!-- wp:code -->
Unchanged: <pre class="wp-block- code"><code>bool header_previous_ available(Header *header) {Unchanged: <pre class="wp-block- code"><code>bool header_previous_ available(Header *header) {
Unchanged: return (header-&gt;previous != NULL) &amp;&amp; header-&gt;previous- &gt;available;Unchanged: return (header-&gt;previous != NULL) &amp;&amp; header-&gt;previous- &gt;available;
Unchanged: }Unchanged: }
Unchanged: bool header_next_available(Header *header) {Unchanged: bool header_next_available(Header *header) {
Unchanged: return (header-&gt;next != NULL) &amp;&amp; header-&gt;next- &gt;available;Unchanged: return (header-&gt;next != NULL) &amp;&amp; header-&gt;next- &gt;available;
Unchanged: }</code></pre>Unchanged: }</code></pre>
Unchanged: <!-- /wp:code -->Unchanged: <!-- /wp:code -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>Pronto, agora temos quatro novas ferramentas que irão nos ajudar a fundir blocos disponíveis. Vamos em frente!</p>Unchanged: <p>Pronto, agora temos quatro novas ferramentas que irão nos ajudar a fundir blocos disponíveis. Vamos em frente!</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:heading -->Unchanged: <!-- wp:heading -->
Unchanged: <h2 class="wp-block- heading">Procurando blocos livres adjacentes</h2>Unchanged: <h2 class="wp-block- heading">Procurando blocos livres adjacentes</h2>
Unchanged: <!-- /wp:heading -->Unchanged: <!-- /wp:heading -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>Para juntar blocos de memória livres e adjacentes, precisamos, no momento da desalocação, verificar se o bloco anterior ou o bloco posterior estão disponíveis. Podemos fazer isso criando duas variáveis: uma para apontar para o primeiro bloco livre e outra para o último bloco livre. Inicialmente, ambas apontarão para o bloco que está sendo desalocado.</p>Unchanged: <p>Para juntar blocos de memória livres e adjacentes, precisamos, no momento da desalocação, verificar se o bloco anterior ou o bloco posterior estão disponíveis. Podemos fazer isso criando duas variáveis: uma para apontar para o primeiro bloco livre e outra para o último bloco livre. Inicialmente, ambas apontarão para o bloco que está sendo desalocado.</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:code -->Unchanged: <!-- wp:code -->
Unchanged: <pre class="wp-block- code"><code>Header *header_merge(Header *header) {<br> Header *first_available = header;<br> Header *last_available = header;</code></pre>Unchanged: <pre class="wp-block- code"><code>Header *header_merge(Header *header) {<br> Header *first_available = header;<br> Header *last_available = header;</code></pre>
Unchanged: <!-- /wp:code -->Unchanged: <!-- /wp:code -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>Se o bloco anterior ao atual estiver livre, <code>first_available</code> aponta para ele.</p>Unchanged: <p>Se o bloco anterior ao atual estiver livre, <code>first_available</code> aponta para ele.</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:code -->Unchanged: <!-- wp:code -->
Unchanged: <pre class="wp-block- code"><code> if (header_previous_ available(header)) {<br> first_available = header-&gt;previous;<br> }</code></pre>Unchanged: <pre class="wp-block- code"><code> if (header_previous_ available(header)) {<br> first_available = header-&gt;previous;<br> }</code></pre>
Unchanged: <!-- /wp:code -->Unchanged: <!-- /wp:code -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>De modo análogo, se o próximo bloco estiver disponível, <code>last_available</code> deve apontar para ele</p>Unchanged: <p>De modo análogo, se o próximo bloco estiver disponível, <code>last_available</code> deve apontar para ele</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:code -->Unchanged: <!-- wp:code -->
Unchanged: <pre class="wp-block- code"><code> if (header_next_ available(header)) {<br> last_available = header-&gt;next;<br> }</code></pre>Unchanged: <pre class="wp-block- code"><code> if (header_next_ available(header)) {<br> last_available = header-&gt;next;<br> }</code></pre>
Unchanged: <!-- /wp:code -->Unchanged: <!-- /wp:code -->
Unchanged: <!-- wp:heading {"level":3} -->Unchanged: <!-- wp:heading {"level":3} -->
Unchanged: <h3 class="wp-block- heading">Quando não há blocos livres</h3>Unchanged: <h3 class="wp-block- heading">Quando não há blocos livres</h3>
Unchanged: <!-- /wp:heading -->Unchanged: <!-- /wp:heading -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>Caso não haja blocos livres nem à frente nem antes do bloco recém-desalocado, não há nada a ser fundido. Neste caso, as variáveis <code>first_available</code> e <code>last_available</code> serão iguais a <code>header</code>, e nossa função simplesmente retornará o ponteiro para o bloco que foi passado a ela.</p>Unchanged: <p>Caso não haja blocos livres nem à frente nem antes do bloco recém-desalocado, não há nada a ser fundido. Neste caso, as variáveis <code>first_available</code> e <code>last_available</code> serão iguais a <code>header</code>, e nossa função simplesmente retornará o ponteiro para o bloco que foi passado a ela.</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:code -->Unchanged: <!-- wp:code -->
Unchanged: <pre class="wp-block- code"><code> if ((first_available == header) &amp;&amp; (last_available == header)) {Unchanged: <pre class="wp-block- code"><code> if ((first_available == header) &amp;&amp; (last_available == header)) {
Unchanged: return header;Unchanged: return header;
Unchanged: }</code></pre>Unchanged: }</code></pre>
Unchanged: <!-- /wp:code -->Unchanged: <!-- /wp:code -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p><strong>Nota:</strong> Não precisamos verificar o bloco anterior ao anterior, ou o posterior ao posterior, e assim por diante. Se, em cada chamada de <code>abfree()</code>, fundimos o bloco com qualquer vizinho livre, é impossível ter dois blocos livres consecutivos. Portanto, basta verificar apenas os vizinhos imediatos.</p>Unchanged: <p><strong>Nota:</strong> Não precisamos verificar o bloco anterior ao anterior, ou o posterior ao posterior, e assim por diante. Se, em cada chamada de <code>abfree()</code>, fundimos o bloco com qualquer vizinho livre, é impossível ter dois blocos livres consecutivos. Portanto, basta verificar apenas os vizinhos imediatos.</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:heading {"level":3} -->Unchanged: <!-- wp:heading {"level":3} -->
Unchanged: <h3 class="wp-block- heading">Atualizando o tamanho quando há blocos livres</h3>Unchanged: <h3 class="wp-block- heading">Atualizando o tamanho quando há blocos livres</h3>
Unchanged: <!-- /wp:heading -->Unchanged: <!-- /wp:heading -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>Caso alguma das variáveis <code>first_available</code> ou <code>last_available</code> não seja igual a <code>header</code>, precisaremos fundir os blocos. Para isso, precisamos realizar duas ações.</p>Unchanged: <p>Caso alguma das variáveis <code>first_available</code> ou <code>last_available</code> não seja igual a <code>header</code>, precisaremos fundir os blocos. Para isso, precisamos realizar duas ações.</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>Primeiro, devemos atualizar o tamanho do primeiro bloco disponível para incluir o último bloco. Para isso, obtemos o ponteiro que aponta logo após o último bloco disponível.</p>Unchanged: <p>Primeiro, devemos atualizar o tamanho do primeiro bloco disponível para incluir o último bloco. Para isso, obtemos o ponteiro que aponta logo após o último bloco disponível.</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:code -->Unchanged: <!-- wp:code -->
Unchanged: <pre class="wp-block- code"><code> void *end = header_address_ after_block(last_available) ;</code></pre>Unchanged: <pre class="wp-block- code"><code> void *end = header_address_ after_block(last_available) ;</code></pre>
Unchanged: <!-- /wp:code -->Unchanged: <!-- /wp:code -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>O tamanho do novo bloco será a diferença entre este ponteiro e o endereço do bloco de usuário:</p>Unchanged: <p>O tamanho do novo bloco será a diferença entre este ponteiro e o endereço do bloco de usuário:</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:code -->Unchanged: <!-- wp:code -->
Unchanged: <pre class="wp-block- code"><code> size_t size = end - header_user_area( first_available) ;E</code></pre>Unchanged: <pre class="wp-block- code"><code> size_t size = end - header_user_area( first_available) ;E</code></pre>
Unchanged: <!-- /wp:code -->Unchanged: <!-- /wp:code -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>Uma vez que tenhamos o tamanho, só precisamos atualizar o primeiro bloco disponível:</p>Unchanged: <p>Uma vez que tenhamos o tamanho, só precisamos atualizar o primeiro bloco disponível:</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:code -->Unchanged: <!-- wp:code -->
Unchanged: <pre class="wp-block- code"><code> header_init(first_available, size, true);</code></pre>Unchanged: <pre class="wp-block- code"><code> header_init(first_available, size, true);</code></pre>
Unchanged: <!-- /wp:code -->Unchanged: <!-- /wp:code -->
Unchanged: <!-- wp:heading {"level":3} -->Unchanged: <!-- wp:heading {"level":3} -->
Unchanged: <h3 class="wp-block- heading">Atualizando ponteiros do bloco fundido</h3>Unchanged: <h3 class="wp-block- heading">Atualizando ponteiros do bloco fundido</h3>
Unchanged: <!-- /wp:heading -->Unchanged: <!-- /wp:heading -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>Com o tamanho do bloco atualizado, precisamos ajustar seus ponteiros. Para o ponteiro para trás, ele deve passar a apontar para o bloco anterior ao primeiro bloco disponível:</p>Unchanged: <p>Com o tamanho do bloco atualizado, precisamos ajustar seus ponteiros. Para o ponteiro para trás, ele deve passar a apontar para o bloco anterior ao primeiro bloco disponível:</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:code -->Unchanged: <!-- wp:code -->
Unchanged: <pre class="wp-block- code"><code> Header *previous = first_available- &gt;previous; </code></pre>Unchanged: <pre class="wp-block- code"><code> Header *previous = first_available- &gt;previous; </code></pre>
Unchanged: <!-- /wp:code -->Unchanged: <!-- /wp:code -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>Já o próximo deve ser o que se seguia ao último bloco disponível:</p>Unchanged: <p>Já o próximo deve ser o que se seguia ao último bloco disponível:</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:code -->Unchanged: <!-- wp:code -->
Unchanged: <pre class="wp-block- code"><code> Header *next = last_available- &gt;next;</code></pre>Unchanged: <pre class="wp-block- code"><code> Header *next = last_available- &gt;next;</code></pre>
Unchanged: <!-- /wp:code -->Unchanged: <!-- /wp:code -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>Uma vez que tenhamos esses valores, basta conectá-los adequadamente utilizando a função <code>header_ plug()</code>:</p>Unchanged: <p>Uma vez que tenhamos esses valores, basta conectá-los adequadamente utilizando a função <code>header_ plug()</code>:</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:code -->Unchanged: <!-- wp:code -->
Unchanged: <pre class="wp-block- code"><code> header_plug(first_available, previous, next);</code></pre>Unchanged: <pre class="wp-block- code"><code> header_plug(first_available, previous, next);</code></pre>
Unchanged: <!-- /wp:code -->Unchanged: <!-- /wp:code -->
Unchanged: <!-- wp:heading {"level":3} -->Unchanged: <!-- wp:heading {"level":3} -->
Unchanged: <h3 class="wp-block- heading">Caso de borda: o último bloco</h3>Unchanged: <h3 class="wp-block- heading">Caso de borda: o último bloco</h3>
Unchanged: <!-- /wp:heading -->Unchanged: <!-- /wp:heading -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>Um último cuidado que devemos ter é considerar que o novo bloco pode vir a ser o último. Neste caso, o bloco que criamos deve se tornar o último bloco agora.</p>Unchanged: <p>Um último cuidado que devemos ter é considerar que o novo bloco pode vir a ser o último. Neste caso, o bloco que criamos deve se tornar o último bloco agora.</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:code -->Unchanged: <!-- wp:code -->
Unchanged: <pre class="wp-block- code"><code> if (last_available == last) {<br> last = first_available;<br> }<br> return first_available; <br>}</code></pre>Unchanged: <pre class="wp-block- code"><code> if (last_available == last) {<br> last = first_available;<br> }<br> return first_available; <br>}</code></pre>
Unchanged: <!-- /wp:code -->Unchanged: <!-- /wp:code -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>Com isso, nossa função de fusão está implementada.</p>Unchanged: <p>Com isso, nossa função de fusão está implementada.</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:heading -->Unchanged: <!-- wp:heading -->
Unchanged: <h2 class="wp-block- heading">Utilizando <code>header_ merge()</code> em <code>abfree( )</code></h2>Unchanged: <h2 class="wp-block- heading">Utilizando <code>header_ merge()</code> em <code>abfree( )</code></h2>
Unchanged: <!-- /wp:heading -->Unchanged: <!-- /wp:heading -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>Agora que temos uma função que une blocos livres, alteramos <code>abfree()</code> para invocá-la no <em>header</em> do bloco a ser desalocado. Feito isso, prosseguimos com a liberação de memória</p>Unchanged: <p>Agora que temos uma função que une blocos livres, alteramos <code>abfree()</code> para invocá-la no <em>header</em> do bloco a ser desalocado. Feito isso, prosseguimos com a liberação de memória</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:code -->Unchanged: <!-- wp:code -->
Unchanged: <pre class="wp-block- code"><code> Header *header = (Header*) ptr - 1;Unchanged: <pre class="wp-block- code"><code> Header *header = (Header*) ptr - 1;
Unchanged: header = header_merge(header);Unchanged: header = header_merge(header);
Unchanged: if (header == last) {</code></pre>Unchanged: if (header == last) {</code></pre>
Unchanged: <!-- /wp:code -->Unchanged: <!-- /wp:code -->
Unchanged: <!-- wp:heading -->Unchanged: <!-- wp:heading -->
Unchanged: <h2 class="wp-block- heading">Conclusão</h2>Unchanged: <h2 class="wp-block- heading">Conclusão</h2>
Unchanged: <!-- /wp:heading -->Unchanged: <!-- /wp:heading -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>Aqui está a função <code>abfree()</code> completa:</p>Unchanged: <p>Aqui está a função <code>abfree()</code> completa:</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->
Unchanged: <!-- wp:code -->Unchanged: <!-- wp:code -->
Unchanged: <pre class="wp-block- code"><code>void abfree(void *ptr) {Unchanged: <pre class="wp-block- code"><code>void abfree(void *ptr) {
Unchanged: if (ptr == NULL) {Unchanged: if (ptr == NULL) {
Unchanged: return;Unchanged: return;
Deleted: } Added: }
Unchanged: Header *header = (Header*) ptr - 1;Unchanged: Header *header = (Header*) ptr - 1;
Unchanged: header = header_merge(header);Unchanged: header = header_merge(header);
Unchanged: if (header == last) {Unchanged: if (header == last) {
Unchanged: while (header_previous_ available(header)) {Unchanged: while (header_previous_ available(header)) {
Deleted: header = header-&gt;previous; Added: header = header->previous;
Deleted: } Added: }
Deleted: last = header-&gt;previous; Added: last = header->previous;
Unchanged: if (last != NULL) {Unchanged: if (last != NULL) {
Deleted: last-&gt;next = NULL; Added: last->next = NULL;
Unchanged: } else {Unchanged: } else {
Unchanged: first = NULL;Unchanged: first = NULL;
Deleted: } Added: }
Unchanged: brk(header);Unchanged: brk(header);
Unchanged: } else {Unchanged: } else {
Deleted: header-&gt;available = true; Added: header->available = true;
Deleted: } Added: }
 Added: }
 Added: Header *header_new(Header *previous, size_t size, bool available) {
 Added: Header *header = sbrk(sizeof(Header) + size);
 Added: header_init(header, size, available);
 Added: header_plug(header, previous, NULL);
 Added: return header;
 Added: }
 Added: void header_init( Header *header, size_t size, bool available) {
 Added: header->size = size;
 Added: header->available = available;
 Added: }
 Added: void header_plug(Header *header, Header *previous, Header *next) {
 Added: header->previous = previous;
 Added: if (previous != NULL) {
 Added: previous->next = header;
 Added: }
 Added: header->next = next;
 Added: if (next != NULL) {
 Added: next->previous = header;
 Added: }
 Added: }
 Added: void *header_user_area(Header *header) {
 Added: return header + 1;
 Added: }
 Added: void *header_address_ after_block(Header *header) {
 Added: return header_user_area(header) + header->size;
 Added: }
 Added: bool header_previous_ available(Header *header) {
 Added: return (header->previous != NULL) &amp;&amp; header->previous->available;
 Added: }
 Added: bool header_next_available(Header *header) {
 Added: return (header->next != NULL) &amp;&amp; header->next->available;
 Added: }
 Added: Header *header_merge(Header *header) {
 Added: Header *first_available = header;
 Added: Header *last_available = header;
 Added: if (header_previous_ available(header)) {
 Added: first_available = header->previous;
 Added: }
 Added: if (header_next_ available(header)) {
 Added: last_available = header->next;
 Added: }
 Added: if ((first_available == header) &amp;&amp; (last_available == header)) {
 Added: return header;
 Added: }
 Added: void *end = header_address_ after_block(last_available);
 Added: size_t size = end - header_user_area( first_available);
 Added: header_init(first_available, size, true);
 Added: Header *previous = first_available->previous;
 Added: Header *next = last_available->next;
 Added: header_plug(first_available, previous, next);
 Added: if (last_available == last) {
 Added: last = first_available;
 Added: }
 Added: return first_available;
 Added: }
 Added: Header *header_split(Header *header, size_t size) {
 Added: size_t original_size = header->size;
 Added: if (original_size > size + sizeof(Header)) {
 Added: header->size = original_size - size - sizeof(Header);
 Added: Header *new_header = header_address_ after_block(header);
 Added: header_init(new_header, size, true);
 Added: header_plug(new_header, header, header->next);
 Added: if (header == last) {
 Added: last = new_header;
 Added: }
 Added: return new_header;
 Added: } else {
 Added: return header;
 Added: }
Deleted: } </code></pre> Added: }</code></pre>
Unchanged: <!-- /wp:code -->Unchanged: <!-- /wp:code -->
Unchanged: <!-- wp:paragraph -->Unchanged: <!-- wp:paragraph -->
Unchanged: <p>Com as alterações deste e do último <em>post</em>, o tamanho dos blocos livres deixam de ser um agravante no consumo de memória, e nossa função <code>malloc()</code> aproxima-se de ficar pronta. Há porém, um último problema a ser resolvido: o alinhamento de blocos de memória. Examinaremos isto no próximo <em>post</em>.</p>Unchanged: <p>Com as alterações deste e do último <em>post</em>, o tamanho dos blocos livres deixam de ser um agravante no consumo de memória, e nossa função <code>malloc()</code> aproxima-se de ficar pronta. Há porém, um último problema a ser resolvido: o alinhamento de blocos de memória. Examinaremos isto no próximo <em>post</em>.</p>
Unchanged: <!-- /wp:paragraph -->Unchanged: <!-- /wp:paragraph -->

Note: Spaces may be added to comparison text to allow better line wrapping.

Post a Comment

Your email is never shared. Required fields are marked *

*
*