Pular para o conteúdo principal

Layout de memória de structs e classes

Como a memória é alocada em structs e classes


Seguindo o post de dependências entre headers (Dependência cíclica de headers).

Me perguntaram a razão do C++ não fazer o demangling dos nomes simplesmente quando uma variável de classe é declarada e também porque isso é diferente do Java, onde eu simplesmente coloco o nome da classe e faço um import.



No C++ podemos ter as seguintes declarações de variáveis em uma classe/struct

https://gist.github.com/thiagomg/d06240a47e9997fd7aba

Já é fato conhecido que a declaração de m1 ficará na stack (pilha) e de m2/m3 será um ponteiro. O tipo de alocação de m1 é chamado de value type.

Mas como isso fica alocado em memória ?

Vamos criar uma classe message e dois packs e em seguida verificar o tamanho deles (supondo arquitetura 64-bit)

https://gist.github.com/thiagomg/c1ec3ac4d55865bcab09

Vemos entender isso agora.
Estamos supondo que os endereços no desenho abaixo são relativos aos endereços alocados.

img1

Veja que cada tipo dentro de uma struct é adicionado por completo. Como o compilador precisa saber o tamanho exato de um tipo para poder colocá-lo dentro da struct, ele precisa fazer o parsing do arquivo. No caso da referência ou do ponteiro, somente é alocado o tamanho de um ponteiro (sizeof(void*)).

Isso é o que permite o forward declaration quando se é um ponteiro ou uma referência, já que o único tamanho que o compilador precisa saber é o tamanho de um ponteiro, este que é sempre o mesmo.

Estruturas aninhadas


Como ficaria uma estrutura aninhada então ?

img2

Conforme falamos acima, o compilador coloca os tipos alinhados. Repare pelos offsets na imagem que não há qualquer byte desperdiçado!

Comentários

  1. Bem legal esse post.
    Alinhamento e layout são pedras no sapato de quem precisa persistir estruturas complexas no disco, para depois recuperá-las.

    ResponderExcluir

Postar um comentário

Postagens mais visitadas deste blog

Mestre Iota

Iota é a nona letra do alfabeto grego, ela é equivalente à letra i do nosso alfabeto. Por convenção ou hábito, utilizamos a letra i na programação para indicar algum tipo de incrementador, como por exemplo, em um for-loop . https://gist.github.com/fabiogaluppo/a23894ae743f7dd29274 Curiosamente, iota , como identificador, também é utilizado na programação para indicar uma sequência finita e consecutiva de números inteiros, como por exemplo, [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]. Inclusive, originalmente na STL existia a função iota , inspirada pela linguagem de programação APL , você pode conferir neste link: http://www.sgi.com/tech/stl/iota.html

Valores Aleatórios Simplificados

A partir do C++ 11, foi introduzido o header <random>  com diversos facilitadores para suporte de geração de números aleatórios. A produção destes números é feita através da combinação de duas categorias de objetos: os geradores e os distribuidores. Os geradores, são responsáveis pela geração dos números, e os distribuidores são responsáveis pela transformação dos números gerados em algum tipo de distribuição de probabilidade.  Como por exemplo, uma distribuição normal (aquela da Gaussiana) ou uma distribuição de Pareto (aquela do 80-20). As opções não faltam, como você pode ver nas referências, por exemplo:   http://www.cplusplus.com/reference/random/ ou  http://en.cppreference.com/w/cpp/header/random .

Policy-based design: log writer

Policy-based design Vamos neste artigo dar mais uma pincelada no Policy-based design . Vamos fazer como exemplo uma classe de log. Como este é só um exemplo, não vamos considerar múltiplos parâmetros no log, mas somente uma string, assim não fugiremos do assunto. Uma das coisas mais importantes neste tipo de design é o desacoplamento. Ele é uma excelente alternativa ao uso de interfaces por duas razões: Não gera chamadas virtuais (ou um nível de indireção em tempo de execução) Duck typing ( https://pt.wikipedia.org/wiki/Duck_typing ) Eu gosto bastante desse tipo de design, já usado aqui: http://simplycpp.com/2016/02/05/leitura-de-configuracao-em-c/