26 de maio de 2011

Desmistificando o uso de ponteiros

Uma das grandes vantagens de construir programas em linguagens como C e C++ é que elas são muito próximas do funcionamento de baixo nível dos computadores, o que costuma deixar a performance desses programas superior àquela conseguida com outras linguagens. Essa característica provavelmente explica a posição delas no ranking de linguagens mais usadas: respectivamente a 2a e 3a (em maio/2011).

A força das duas linguagens, no entanto, é também seu calcanhar de Aquiles. Muitos programadores temem C/C++ justamente por causa dessa proximidade com a linguagem de máquina, personificada no uso de um recurso-símbolo : os ponteiros. Alguns fatores contribuem para esse temor mas acredito que o principal é a falta de conhecimento sobre a sua real utilidade e funcionamento.

Então, pra começar, o que são exatamente os "ponteiros" e pra que servem ? Um ponteiro é uma variável cujo conteúdo é um endereço na memória do computador. Em outras palavras, é uma posição de memória que "aponta" para outra posição de memória. Com um diagrama fica mais fácil visualizar o conceito:
Ponteiro

No quadro acima, nome é uma variável do tipo "ponteiro para char". Isto é, o conteúdo dela indica um local na memória do computador que será usado para armazenar caracteres. O que está acontecendo no programa retratado é uma alocação dinâmica de memória, onde o sistema operacional faz para nós a reserva de uma posição da memória e coloca o endereço reservado na nossa variável. Podemos, então, usar esse ponteiro para acessar o conteúdo da memória reservada.

Os ponteiros, portanto, flexibilizam o desenho de uma aplicação, permitindo a ela alocar memória dinamicamente para tratar situações nas quais não sabemos de antemão com quantos elementos teremos que lidar. Isso também permite adiar a alocação até que os elementos sejam efetivamente necessários, reduzindo o consumo de memória. Ainda, no caso de classes, a solução para o tratamento de heranças é uma implementação fortemente calcada em ponteiros.

Uma outra característica dos ponteiros é que eles facilitam o fluxo das informações dentro do programa; sem eles, passar estruturas grandes como parâmetro exigiria a movimentação de grande quantidade de bytes enquanto com eles é necessário trafegar apenas os bytes que carregam o endereço de memória (a quantidade exata depende do tipo de arquitetura do sistema mas em Win32 são 4 bytes).

Isso tudo levanta, então, outras questões: quando usar exclusivamente o ponteiro no meu código, quando e como acessar o conteúdo e que sintaxe usar para diferenciar ambos os casos ?

Na figura no início do post aparece o uso mais comum dos ponteiros, que é manter referência a alguma memória alocada dinamicamente. Obviamente, armazenar o endereço alocado é imprescindível para que possamos acessar o seu conteúdo e também para devolver a memória ao sistema operacional quando não formos mais usá-la.
typedef struct {
bool Assigned;
long Id;
char Nome[51];
double Saldo;
} TWPessoa;

TWPessoa *lPessoa = new TWPessoa;
/* ... */
delete lPessoa;
lPessoa = NULL;

O valor NULL é um ponteiro especial para indicar que uma variável não está apontando para lugar algum, isto é, que a variável não está alocada.

Como regra, se o nome da variável aparece sozinho no código, sem decorações (como pontos, setas ou asteriscos) então estamos trabalhando com a variável ponteiro. Nesta situação, o que temos é o endereço de memória para onde nossa variável aponta. É o que está acontecendo no quadro anterior, onde a memória para a estrutura é alocada e o endereço que o sistema operacional reservou para ela é jogado em nossa variável.

A passagem de um ponteiro por parâmetro é outro uso corriqueiro. Formalmente, isso é conhecido como "passagem por referência", o que significa que apenas o endereço é trafegado. É por essa razão que as alterações feitas ao conteúdo de um parâmetro passado por referência são enxergadas também fora da função: ambos os lados apontam exatamente o mesmo endereço na memória.

Quando há alguma decoração anexada à variável no código, então estamos nos referindo ao conteúdo apontado por essa variável. Em C/C++, há várias sintaxes diferentes para acessar o conteúdo apontado, como mostra o trecho abaixo:
/* As 3 linhas abaixo fazem exatamente a mesma coisa :
Vai até a posição de memória "apontada" por lPessoa;
No local reservado para a variável Assigned, coloque o valor true. */

lPessoa->Assigned = true;

lPessoa[0].Assigned = true;

(*lPessoa).Assigned = true;

O C/C++ ainda tem um sintaxe para que você possa recuperar o endereço de uma variável de alocação estática, independentemente se é um tipo atômico (int, double, char, etc.) ou um tipo criado pelo usuário (struct, class). Poder fazer essa recuperação é útil, por exemplo, para evitar trafegar o dado estático. Novamente, aqui você só trafegaria os bytes relativos ao ponteiro:
TWPessoa lPessoaEstatica;
ResetaPessoa (&lPessoaEstatica);

Pelo rumo dessa discussão, percebemos que qualquer que seja a linguagem utilizada por você, com certeza ela utiliza ponteiros internamente - mesmo que de forma disfarçada - já que eles são a base para o acesso à memória do computador. Assim, conhecer e utilizar bem esse recurso é um excelente começo para construir bons programas em qualquer linguagem.

19 de maio de 2011

Enviando emails com Delphi - Parte III

Vida de programador é difícil... No início de 2010, o Google fez uma alteração no sistema online de email deles, o GMail, para substituir o método de segurança SSL então vigente no serviço pela sua versão mais nova, chamada TLS.

Por causa dessa modificação simples, muitos programas que antes conseguiam enviar email tranquilamente através do GMail falharam. Para piorar, a versão 9 do Indy não implementa nativamente o tratamento do TLS - isso só aconteceu a partir da versão 10. Ou seja, programas Delphi ou C++ Builder construídos com o Indy 9 não tinham uma solução fácil à mão para essa questão.

Na versão 10 do Indy, a solução é extremamente simples : basta configurar a propriedade UseTLS da instância de IdSMTP e manter as demais configurações:
IdSMTP1.UseTLS := utUseExplicitTLS;

Manter as demais configurações significa que o servidor deve continuar sendo smtp.gmail.com, a porta 587, com autenticação de usuário e senha. Também é obrigatório atribuir um handler para tratar a comunicação SSL/TLS. Para mais informações sobre isso e outros aspectos das configurações básicas, veja este post.

Embora não seja um processo tão direto, é possível trabalhar com TLS em Indy 9. Basicamente, é preciso enviar ao servidor de email um comando STARTTLS logo após o SMTP ter se conectado. O trecho abaixo é um código genérico que testa configurações internas para determinar se a conexão é segura. Em caso positivo, um handler é destacado para fazer o tratamento da conexão. Neste ponto, o SMTP já foi preparado com as configurações básicas necessárias.
if (TipoSeguranca = SEGURANCA_SSL) Or (TipoSeguranca = SEGURANCA_TLS) then
begin
IdSMTP.IOHandler := IdSSLIOHandlerSocket;
if (TipoSeguranca = SEGURANCA_TLS) then
begin
IdSSLIOHandlerSocket.SSLOptions.Method := sslvTLSv1;
IdSSLIOHandlerSocket.PassThrough := true;
end;
end;

{ Tenta conectar no servidor com 1 minuto de timeout }
IdSMTP.Connect (60000);

{ Emula o comportamento do TLS }
if (TipoSeguranca = SEGURANCA_TLS) then
begin
IdSMTP.SendCmd('STARTTLS', 220);
IdSSLIOHandlerSocket.PassThrough := false;
end;

if (Autentica And (not IdSMTP.Authenticate () ) then
Raise Exception.Create ('Falha na autenticação do usuário');

Ao detectar que a conexão segura exige TLS, alguns ajustes precisam ser feitos. Primeiro, mudo o método de segurança do handler para que adote o padrão para TLS. Depois, instruo o handler a codificar os comandos trocados entre ele e o servidor. Só então, podemos estabelecer a conexão.

Uma vez que a conexão está estabelecida, enviamos ao servidor o comando STARTTLS para ativar a comunicação segura na mesma porta. Por causa disso, o PassThrough que forçamos antes da conexão já pode ser desligado.

Autenticar manualmente o usuário e a senha é um preciosismo pois o método Send para envio da mensagem o fará por nós. Aqui no exemplo foi feita a autenticação explícita pra mostrar que é possível interceptar um erro de usuário/senha inválido antes de se tentar enviar a mensagem.

Agora, é só preparar uma instância do idMessage com os dados da mensagem (destinatários, assunto, corpo da mensagem, etc.) e enviá-la com o SMTP.

As considerações tecidas neste post também são válidas para quem usa o Hotmail como serviço para envio de email em suas aplicações. Há apenas duas diferenças importantes : o servidor de email, claro, é outro (smtp.live.com); também a forma de se especificar o usuário do serviço difere. No GMail, deve ser usado como nome do usuário somente o texto que vem antes do arroba (@) do endereço de email, enquanto no Hotmail o nome do usuário é o endereço completo.

Mais Informações
Enviando emails com Delphi - Parte I e Parte II, STARTTLS

9 de maio de 2011

Enviando emails com Delphi - Parte II

Há alguns dias, escrevi um post sobre o envio de emails com Delphi, mostrando a configuração básica dos componentes Indy para SMTP e também as funções que devem ser chamadas para completar o processo. No exemplo, a mensagem incluída no email era um texto simples, sem qualquer tipo de formatação.

No começo, os programas leitores de email só conseguiam trabalhar com mensagens assim, onde apenas texto era trocado. É um comportamento básico mas que ainda tem sua utilidade, principalmente quando há questões de segurança envolvidas. Com a evolução da internet, entretanto, praticamente todos os leitores de email conseguem exibir mensagens com formatação rica. Usando HTML podemos compor emails com layouts complexos, usando cores e tipos de fontes diferentes, além da inclusão de imagens, links, tabelas, animações, entre outros. Uma grande vantagem desse formato é que ele já é utilizado para construir os sites da internet. Ou seja, HMTL é uma ferramenta bastante conhecida e amplamente suportada.

Do ponto de vista do envio de email, o que há de diferente em relação ao que foi apresentado no outro post ? Basicamente, apenas dois detalhes. O primeiro é uma propriedade da mensagem que determina o tipo de conteúdo que a mensagem está trafegando. Essa característica é chamada MIME (Multipurpose Internet Mail Extensions, ou Extensões Multipropósito para Correio na Internet). O padrão para essa propriedade no corpo de um email é o valor text/plain, que significa que a mensagem é composta por um texto simples. Como queremos montá-la como um HTML, temos que avisá-la disso:
IdMessage1.ContentType := 'text/html';
IdMessage1.CharSet := 'ISO-8859-1';

Veja que eu também modifiquei o charset da mensagem. Esta propriedade indica qual é o conjunto de caracteres que a mensagem está usando. Como o português usa acentuação, é preferível trocar o padrão americano pelo conjunto latino ('ISO-8859-1').

O outro detalhe é que o corpo da mensagem agora tem que respeitar o MIME configurado. Quero dizer com isso que teremos que montar um HTML para a mensagem:
IdMessage1.Body.Text := '<html><head>' +
'<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">' +
'</head><body>' +
'<p>Essa mensagem é um <b>Teste</b> de email HTML.</p>' +
'</body></html>';

Embora pareça redundante, é importante informar de novo no cabeçalho do HTML quem é o MIME e o charset. Os leitores de email utilizam as informações desse cabeçalho para renderizar a mensagem recebida via SMTP.

E se quisermos incluir uma imagem em nosso HTML ? Algumas pessoas publicam a imagem na internet e referenciam o link dela no HTML da mensagem. Mas essa solução exige que o destinatário esteja conectado para poder buscar a imagem, coisa que nem sempre é verdade. Numa empresa, por exemplo, as mensagens são recebidas de forma centralizada por um servidor de email, dispensando a necessidade de ter internet local. Muitas delas adotam ainda restrições ao acesso à internet.

Uma maneira melhor de se fazer isso é enviar a imagem junto com o HTML. Ao invés de preencher o campo Body da mensagem, teremos que decompô-la em seus constituintes básicos para podermos identificar de forma separada o MIME de cada um. Isto é, o corpo da mensagem é um HTML enquanto a imagem é um arquivo binário com MIME próprio. O conjunto todo terá um MIME especial (multipart/mixed) que sinaliza que a mensagem está montada como múltiplas partes independentes.

Cada parte deverá ser anexada à mensagem através da propriedade MessageParts. Para o corpo, usamos o tipo TIdText. Para a imagem, o tipo tradicional para anexos (TIdAttachmentFile).
var
text : TIdText;
at : TIdAttachmentFile;
begin
IdMessage1.MessageParts.Clear();
IdMessage1.ContentType := 'multipart/mixed';

text := TIdText.Create (IdMessage1->MessageParts, Nil);
text.ContentType := 'text/html';
text.CharSet := 'ISO-8859-1';
text.Body.Text := PreparaHTML();

at := TIdAttachmentFile.Create (IdMessage1->MessageParts,
'C:\\Inetpub\\wwwroot\\winxp.gif');
at.ContentType := 'image/gif';
at.FileName := 'winxp.gif';

IdSMTP1.Connect();
IdSMTP1.Send(IdMessage1);
{ ... }

O HTML pode, então, fazer referência diretamente ao nome do arquivo anexado, sem precisar estipular um endereço na internet. A única coisa é que o nome do arquivo deve ser exatamente igual àquele informado na propriedade FileName do anexo:
function TForm1.PreparaHTML : String;
begin
{ ... }
Result := Result + '<img style="margin:1px 1px 1px 0px;" src="winxp.gif" />';
{ ... }
end;

Em tese, não há restrição a quantos recursos externos podem ser agregados ao email usando esse tipo de construção. Também não se restringe à inclusão de imagens, podendo ser usado para incorporar animações, scripts, folhas de estilo, etc. - desde que tenham os respectivos MIMEs devidamente configurados.

Estou com a versão 10 do Indy que vem com o Delphi XE mas acredito que os recursos mostrados aqui estejam disponíveis em versões anteriores também.

Mais Informações
Enviando emails com Delphi

5 de maio de 2011

Invenção da Intel amplia sobrevida da base tecnológica dos atuais transístores

Já vi e ouvi em mais de uma fonte que o limite da miniaturização dos componentes eletrônicos está chegando ao seu limite, imposto pela impossibilidade física de se manipular algo menor do que um átomo. Quer dizer, o menor transístor possível, no limite, seria em tese um único átomo.

É uma implicação natural da lei de Moore, postulada em 1965 por Gordon Moore, co-fundador da Intel, e que diz que o número de transístores que podem ser inseridos num circuito integrado dobra a cada dois anos sem aumento de custos. Essa característida está intimamente ligada à capacidade de processamento dos aparelhos eletrônicos e quanta informação eles conseguem armazenar. Mas, uma hora não haverá mais espaço físico para aumentar a quantidade de transístores num chip ...

Com isso, especula-se muito que tecnologia substituirá aquela na qual os atuais transístores se baseiam. Talvez algo que explore a mecânica quântica ou que seja baseado nas propriedades da luz.

Mas, não é que a Intel ainda está conseguindo avançar com o bom e velho silício mesmo ? Essa semana, eles anunciaram que vão dar início à produção de chips cujos transístores são construídos numa nova arquitetura, tridimensional, que é mais eficiente e mais econômica do que a atualmente em uso e que é montada num plano (arquitetura bidimensional).

O texto que vai abaixo é reportagem da ComputerWorld que aborda a "reinvenção dos transistores" pela Intel, usando tecnologia 3D.

A Intel anunciou nesta quarta-feira o que considera um avanço significativo na evolução do transistor, o componente que há mais de 50 anos é a pedra-fundamental da indústria eletrônica. A empresa irá iniciar a produção em larga escala de chips baseados em um transistor com design "tridimensional", que possibilita melhor desempenho e menor consumo de energia quando comparado aos transistores "planos" atuais.

O design foi batizado pela empresa de "Tri-Gate", e originalmente apresentado em 2002. Produzidos em um processo de 22 nanômetros, os novos componentes tem desempenho 37 por cento superior aos componentes de 32 nm utilizados atualmente em processadores como os da família "Sandy Bridge" quando operando em baixa voltagem. Quando operando no mesmo nível de desempenho dos transistores atuais, os "Tri-Gate" tem consumo de energia até 50% menor.

Transistores operam como interruptores: o fluxo da corrente elétrica é controlado por uma parte chamada Gate (comporta), que permite ou não a passagem de energia em um canal entre a fonte (Source) e o dreno (Drain).

O design Tri-Gate substitui o canal plano e um único Gate sobre ele por uma fina lâmina de silício que se projeta acima do substrato do transistor, envolta por três Gates (dois nos lados, um no topo). O controle extra permite fluxo máximo de corrente quando o transistor está "ligado" (o que ajuda o desempenho), e o mínimo possível quando desligado (reduzindo o desperdício de energia), além de permitir que o componente alterne rapidamente entre os dois estados.

Transistor plano X Transistor 3D
Esta ilustração compara um transistor plano (esquerda) a um Tri-Gate (direita)

A próxima geração de processadores Intel, de codinome "Ivy Bridge", será a primeira a utilizar os novos transistores Tri-Gate. A Intel demonstrou hoje notebooks, desktops e servidores operando com processadores "Ivy Bridge", que devem entrar em produção em larga escala no final deste ano. Graças à tecnologia Tri-Gate a empresa espera produzir chips com transistores em processo de 14 nanômetros em 2013, e 10 nanômetros em 2015.

O link para a reportagem original está disponível no quadro abaixo.