# VTable
Caloni, 2011-03-01 <computer> [up] [copy]Acho que na breve história desse blogue nunca contei a história do vtable. No máximo fizemos um hookzinho nos métodos de um componente COM. Mas só.
Não encontro uma analogia simples, assim, de cabeça. Então vou contar no cru, mesmo. Talvez seja até mais divertido.
A vtable foi um mecanismo criado para implementar o polimorfismo em C++ quando falamos de ponteiros para classes base cujos métodos virtuais foram sobrescritos por uma classe derivada.
A coisa fica mais simples quando explicamos que em C++ você só paga pelo que usa. Se você declarar uma classe que não tenha nenhum método virtual, os objetos dessa classe não precisarão de uma vtable. No entanto, você não conseguirá sobrescrever um método dessa classe através de uma derivada:
#include <iostream> class C { public: void method() { std::cout << "C::method\n"; } }; class D : public C { public: void method() { std::cout << "D::method\n"; } }; void func(C* c) { c->method(); } int main() { D d; func(&d); // passa endereço de C "dentro de D" } Saída ===== C::method
No exemplo acima, a chamada feita em func irá chamar o método da classe C, mesmo que a classe D tenha sobrescrito esse método. O programador semi-experiente deve pensar "lógico, ela não é virtual!", e está certo, assim como qualquer pessoa que decora essas formulazinhas de vestibular.
Para criarmos polimorfismo de verdade, precisamos declarar o método em C como virtual:
class C { public: virtual void method(); };
Agora sim, a chamada em func irá ser para D::method.
Pergunte para o programador semi-experiente em C++ por que as coisas são assim e provavelmente ele irá falar algo sobre vtable, mesmo que não saiba exatamente como ela funciona.
A vtable é uma tabela que guarda o endereço dos métodos virtuais de uma classe. Se uma classe derivada sobrescrever um ou mais métodos de sua classe base, ela terá uma outra vtable com os endereços dos métodos "corrigidos".
Dessa forma, algo um pouco diferente ocorre na chamada c->method() quando estamos lidando com classes polimórficas: o início de um objeto dessa classe terá um ponteiro para a vtable de sua classe. Quando um método virtual é chamado, em vez do compilador gerar uma chamada estática para o endereço do método da classe cujo tipo estamos usando, ele irá redirecionar essa chamada para uma posição na vtable para onde esse objeto aponta. No caso de um objeto do tipo D, a entrada para method em sua vtable apontará não para C::method, mas para D::method, uma função com a mesma assinatura contida na classe base C e que, portanto, a sobrescreve.
Façamos um pequeno teste para comprovar o que falamos. Vamos escancarar a chamada feita a partir de uma instância de D e a partir de uma instância de C. Nada que um WinDbg não resolva de braços cruzados:
int main() { D d; C c; func(&d); func(&c); } cl /Zi vtable3.cpp windbg vtable3.exe
# Projeto DayToDay
Caloni, 2011-03-03 [up] [copy]O DayToDay é um projetinho que criei para fazer tracking das minhas atividades diárias. Eu o criei há mais de 6 anos, e provavelmente se tivesse pensado em como isso seria útil para as pessoas compartilharem suas ideias e limitasse o número de caracteres para 140, estaria rico hoje.
O "conceito" é bem simples: executo o programa, ele exibe um campo texto para digitar o que estou fazendo, digito enter ou clico no botão de OK e ele fecha. O que eu digitei cai em um arquivo texto com o mesmo nome do programa.
Algumas "features" avançadas que é bom saber:
* Ele gera o arquivo texto em UNICODE. Na época em que eu digitava em russo, isso era importante.
* Ele já gera suas anotações com data e hora.
* Você pode gerar um atalho para chamá-lo rapidamente e definir um diretório de trabalho diferente: o arquivo será gerado no diretório de trabalho especificado, e não onde está o executável.
* Existe uma versão em .NET que fiz na época que estudava C#. Felizmente eu perdi esse projeto.
# Base64
Caloni, 2011-03-09 <computer> [up] [copy]No meio dos meus artigos pendentes, encontrei esse, de Luiz Rocha, que fala sobre a dificuldade de entender o que seria Base64:
Salve Caloni,
Já leio o seu site a algum tempo. Realmente acho complicado, alguns eu nem entendo =D. Mais eh o seguinte, eu estou montando um projeto, mas eu não entendo nada de trabalhar com binários. Então pesquisei na internet, e achei um algoritmo que pode me ajudar, [na lógica]. É o base64 mas eu não entendi como ele converte e desconverte em binário. Será que vc pode me ajudar, obrigado!!
Não é a primeira pessoa que pede informações sobre algo específico demais para explicar (para isso existe a Wikipedia e o Google, não?). No meio da minha escrita, percebi que já havia escrito sobre os fundamentos do conhecimento por trás da criação do Base64, conhecimento esse, acredito eu, todo programador que quer sair do lugar com os próprios pés deve ter.
* Básico do básico: binário <-- Luiz, você está procurando por esse!
Bônus:
* Passagem por valor e emails com anexo
REALMENTE para iniciantes:
* Configurando seus projetos no Visual Studio
* Como criar uma LIB no Visual Studio
Acredito que tudo que um programador precisa saber é o básico. O problema é que esse básico cresce a cada ano, mas, de qualquer forma, continua sendo necessário voltar às raízes de vez em quando, e se existe algo que ele nunca deve esquecer, é isso.
Até porque na programação, 90% não se cria, se copia.
Imaginemos o cenário para a criação do Base64:
Alguns meios de comunicação, notadamente envio de e-mails e a navegação web, por incrível que pareça, trabalham em um protocolo totalmente em modo texto. É até fácil de entender, pois quando essas tecnologias nasceram as limitações de velocidade e estabilidade das conexões permitiam apenas o envio de texto puro de uma ponta a outra.
Isso quer dizer que, na prática, os anexos de um e-mail e as imagens de uma página trafegam, pelo protocolo definido, em modo texto.
Como isso é possível?
A solução não é tão obscura quanto possa parecer. Se um programador médio tivesse esse problema e nenhuma solução existisse ainda, ele faria o que sempre fez para resolver problemas desse tipo: codificar a mensagem na forma permitida. Isso já é feito com o próprio texto, que é apenas uma interpretação de tabelas de caracteres.
Tudo que é necessário fazer é o contrário, mas usando a mesma lógica: montar uma tabela de caracteres válidos e traduzir para um conteúdo binário, sendo que todas as combinações possíveis devem caber nessa tabela.
A forma mais básica binária de comunicação é um byte, constituído por 8 bits, que combinados darão 2^8 entradas em nossa tabela, que precisaria de 256 caracteres diferentes. Como isso ultrapassa o limite dos protocolos que estamos lidando, que em sua maioria utilizam a tabela ascii básica, que possui 128 posições, sendo que algumas posições não possuem caracteres imprimíveis, decidiu-se usar o múltiplo anterior: 64 posições, o que nos dá a chance de codificar 6 bits de cada vez (2^6).
Esse padrão de codificação se chama Base64. Se quiser mais detalhes, basta ler a RFC, que é pequena e muito simples de se ler.
Agora, como codificar essa solução? Só entendendo o básico, é claro.
Wikipedia e o Google: http://www.google.com/search?q=base64
envio de e-mails e a navegação web: http://pt.wikipedia.org/wiki/Hypertext_Transfer_Protocol
# Reorganizando meus feeds (de novo)
Caloni, 2011-03-10 [up] [copy]Depois da minha opinião dada ao Efetividade na matéria sobre ferramentas para gerenciar as leituras tenho que atualizar que não utilizo mais o esquema das estrelinhas, porque acabei me dando conta que nunca lia o que marcava para ler "depois".
Porém, ainda utilizo o Google Reader por uma série de motivos:
* Integrado com as ferramentas Google, que eu venero;
* Tem atalhos no teclado, que eu venero
* Consigo anotar o que quiser em qualquer página que navegar;
* Posso organizar os feeds por categorias.
Minha organização de feeds, até semana passada, usava categorias específicas (programação, cinema, economia) e tinha duas categorias no topo que organizava por frequência (diário, semanal), seguindo uma dica de um leitor do Efetividade. Porém, meu maior problema sempre fora os feeds que cospem milhares de entradas por dia, e que sempre ficava para ler no meu fim-de-semana, consumindo às vezes o dia inteiro!
Por isso, para evitar ser abarrotado de notícias, mantenho a seguinte organização de categorias:
1. Notícias: todos os feeds que cospem milhares de entradas. Organizo por "mágica" e leio apenas os que ficarem no topo. Ao final, clico no famigerado "Mark all as read" e fim de história.
2. Diário: leituras imediatas, que não requerem mais que cinco minutos, como a tirinha do Dilbert e minhas pesquisas cadastradas no Google.
3. Semanal: leitura um pouco mais demorada, para quando tiver mais que 10 minutos sobrando.
4. Amigos: todos os feeds das pessoas que eu conheço e acompanho.
5. Pessoal: meus próprios feeds, para reler o que eu escrevi e capturar "o outro lado da comunicação" (você, leitor).
6. Fóruns: mensagens do grupo de programação C++, por exemplo. Está no final da lista porque posso dedicar um pouco do fim-de-semana para ler a evolução dos tópicos, ou até colaborar quando tiver algum conhecimento a acrescentar.
Além disso, os Shared Itens estão configurados como Start page, sendo que tudo que eu anotar durante minha navegação deve ser lida quando eu abro o Reader (incluindo minhas anotações).
Basicamente é isso. Espero não ter que mudar novamente a estrutura. Se tiver, que seja pra melhor.
Idéias?
# Loucuras multithreading
Caloni, 2011-03-18 [up] [copy]Estava eu depurando um sistema cliente/servidor com um tantão de threads e me veio à cabeça na volta pra casa como que um programador iniciante entenderia aquela bagunça de dar F10 em uma função e cair no meio de outra, dar outro F10 na outra e voltar pra primeira.
Loucura, não?
Nem tanto. O multithreading de um sistema operacional está aí pra isso. O que ocorre, no caso de depurações em uma única IDE, é que os breakpoints temporários que são definidos ao usar o comando de step into/over podem ser ativados em paralelo, simultaneamente.
Mas confesso que, de vez em quando, depurar múltiplas threads fica parecendo coisa de maluco.
O blogue de José Ribeiro Pena Neto, aparentemente recém-criado, conseguiu utilizar minha solução de conversão do dicionário Houaiss para Babylon em algo mais incrívei ainda: converter, em alguns passos, a base de dados do Houaiss para o Amazon Kindle.
De uma maneira simples e efetiva, ele cita o passo-a-passo para a conversão da base Houaiss para o formato Babylon e, a partir disso, reconverter para o formato usado pelo gratuito e multiplataforma Stardict.
# Bazaar com Subversion
Caloni, 2011-03-23 [up] [copy]Para pessoas que ficaram viciadas em commits curtos e todo o histórico do fonte na própria máquina, foi uma surpresa descobrir que com o uso do plugin bzr-svn (já incluso no pacote de instalação), consigo ainda utilizar o Bazaar, mesmo que agora esteja trabalhando com um branch do Subversion.
Na verdade, melhor ainda: o bzr-svn baixa o SVN trunk com todo o histórico na máquina local, como se fosse um branch do próprio Bazaar, e permite a criação de branches desconectados para pequenos commits e o merge final para o servidor SVN.
E o melhor de tudo: não há segredo. Tudo que precisa fazer é instalar o Bazaar e fazer um get/co com o endereço do branch SVN que o plugin se vira sozinho para detectar que se trata do Subversion. (Se for um branch protegido, o usuário e senha serão pedidos durante o processo).
C:\Projetos>bzr co http://subversion.assembla.com/svn/caloni/ caloni Initialising Subversion metadata cache in C:\Users\Caloni\AppData\Local\svn-cache\sbrubles. C:\Projetos>cd caloni C:\Projetos\caloni>bzr qlog C:\Projetos\caloni>bzr get . ..\caloni.local Branched 2 revision(s). C:\Projetos\caloni>cd ..\caloni.local C:\Projetos\caloni.local>vim readme.txt C:\Projetos\caloni.local>bzr ci -m "Commit local" Committing to: C:/Projetos/caloni.local/modified readme.txt Committed revision 3. C:\Projetos\caloni.local>vim readme.txt C:\Projetos\caloni.local>bzr ci -m "Commit local" Committing to: C:/Projetos/caloni.local/modified readme.txt Committed revision 4. C:\Projetos\caloni.local>vim readme.txt C:\Projetos\caloni.local>bzr ci -m "Commit local" Committing to: C:/Projetos/caloni.local/modified readme.txt Committed revision 5. C:\Projetos\caloni.local>cd ..\caloni C:\Projetos\caloni>bzr merge ..\caloni.local M readme.txt All changes applied successfully. C:\Projetos\caloni>bzr st modified: readme.txt pending merge tips: (use -v to see all merge revisions) Wanderley Caloni 2011-03-23 Commit local C:\Projetos\caloni>bzr ci -m "Commit pro servidor" Committing to: http://subversion.assembla.com/svn/caloni modified readme.txtHTTP subversion.assembla.com username: caloni <http://subversion.assembla.com:80> Restricted Area caloni password: Committed revision 3. C:\Projetos\caloni>bzr qlog