# Dependência pedindo carona
Caloni, 2011-01-04 computer [up] [copy]Mesmo as vezes que você não queira, algumas dependências pedem carona e o compilador deixa entrar. Daí mesmo que você não use uma função API, ela acaba te atazanando a vida.
Foi o caso da ToolHelp32 no Windows NT 4.
Quando compilamos, cada CPP vira uma coleção de funções que serão usadas, mais tarde, pelo linker, para juntar a bagunça. Para mais detalhes dessa fascinante história, recomendo o fantástico artigo sobre Os diferentes erros na linguagem C, seção **Linkedição**.
Para as dependências localizadas fora do executável final, por exemplo, as DLLs do sistema, o linker cria uma entrada no formato padrão de executável que adiciona essa dependência extra que será resolvida na hora do programa rodar, quando o loader do sistema operacional terá que fazer um linker on-the-fly, catando todas as DLLs e funções necessárias para colocar o bichinho no ar.
Dessa forma, quando existirem unresolved externals fora do executável final, o responsável por dar o erro é o loader do sistema:
Isso significa que o seu processo não poderá ser executado, pois faltam funções no ambiente que ele depende.
Um recurso muito útil para ver essas funções é o Dependency Walker, meu amigo de infância:
<blockquote>"Mas, Caloni, eu nem uso essa função! Como ela pode ser necessária?"</blockquote>
Pois é. As coisas nem sempre acabam sendo como o esperado. Se você possuir uma LIB, por exemplo, e nela existirem duas funções, como abaixo, e você se limitar a usar em seu programa apenas a primeira, todas as dependências da segunda também irão parar no executável final.
#include "LibMod.h" #include <windows.h> #include <Tlhelp32.h> #include <stdio.h> // Essa função é usada pelo nosso App int UsingOldApis() { DWORD ver = GetVersion(); // API paleozoica, OK. return int( (DWORD)(LOBYTE(LOWORD(ver))) ); } // Essa função NÃO é usada pelo nosso App void UsingNewApis() { // Opa: função moderninha!! if( HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL) ) { PROCESSENTRY32 procEntry; // Tudo bem, nosso App não vai usar essa função. if( Process32First(snapshot, &procEntry) ) { printf("Process list:\n"); do { printf("%s\n", procEntry.szExeFile); } while( Process32Next(snapshot, &procEntry) ); } CloseHandle(snapshot); } } #include "LibMod.h" #include <stdio.h> #include <stdlib.h> int main() { // Usando apenas funções paleozoicas, certo? printf("Our Major OS version is %d\n", UsingOldApis() ); system("pause"); }
Acontece que o nosso amigo linker gera uma lista de dependências por módulo (CPP), e não por função. Dessa forma, tudo que vier é lucro.
Só que às vezes é prejuízo, também. Quando usamos um SO da época do guaraná com rolha, como o Windows NT 4, por exemplo, não conseguimos usar um programa porque este possuía uma função moderninha nunca usada, mas que estava dentro de um CPP junto de uma função comportada, usando apenas APIs documentadas no primeiro papiro da Microsoft.
Sempre existe. Nesse caso, migrarmos as funções moderninhas para um segundo CPP, recompilarmos a LIB e a dependência milagrosamente desaparecerá!
#include "LibMod.h" #include <windows.h> #include <Tlhelp32.h> #include <stdio.h> // Essa função é usada pelo nosso App int UsingOldApis() { DWORD ver = GetVersion(); // API paleozoica, OK. return int( (DWORD)(LOBYTE(LOWORD(ver))) ); } #include "LibMod.h" #include <windows.h> #include <Tlhelp32.h> #include <stdio.h> // Essa função NÃO é usada pelo nosso App void UsingNewApis() { // Opa: função moderninha!! if( HANDLE snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, NULL) ) { PROCESSENTRY32 procEntry; // Tudo bem, nosso App não vai usar essa função. if( Process32First(snapshot, &procEntry) ) { printf("Process list:\n"); do { printf("%s\n", procEntry.szExeFile); } while( Process32Next(snapshot, &procEntry) ); } CloseHandle(snapshot); } }
Agora a aplicação poderá rodar em paz naquele que é, como diz meu amigo, um sistema operacional de ponta... da outra ponta!
# Reunião de programadores C++ (há 5 anos)
Caloni, 2011-01-12 ccppbr [up] [copy]Começo de ano, hora de fazer backup completo. Durante minha cópia anual do gmail acabei encontrando meu post-chamado para nossa primeira reunião C++. Como parte da sessão nostalgia, convido-os, novos e velhos colegas, a continuar a brincadeira de organizar uma reunião informal de pessoas que gostam tanto de programar que criam seus próprios ponteiros.
E-mail escrito em 02/12/2005:
Um dia desses conversando com o Rodrigo Strauss, falando sobre como é interessante trocar informações e experiências sobre C++, ele teve a brilhante e original idéia (ninguém nunca fez isso antes) de propor encontros razoavelmente regulares para fazermos isso. A idéia dele era mais ou menos essa:
* Peridiocidade dos encontros de X em X meses. Ainda não fechamos isso;
* X pautas por reunião, votadas pelos participantes. Já temos algumas sugestões como, recursos arcanos do C++ (essa, de acordo com ele, seria minha função), ferramentas, bibliotecas, organização de código etc;
* Troca de experiências sobre C++ em diversos sistemas operacionais. Por exemplo, nós mostraríamos para o pessoal de UNIX o Visual C++ e aprenderíamos com eles sobre emacs ou KDevelop;
* Começar de forma muito simples, como uma mesa redonda, e se a coisa avançar, arrumar um lugar para palestras e apresentações;
* Reuniões em bares ou restaurantes onde possamos conversar, levar acompanhantes e nos sentirmos seguros levando notebooks ou Pockets. Podemos até subir uma rede wifi e aumentar a diversão :-)
* Como eu e o Strauss somos de São Paulo (na verdade, eu sou de São Bernardo), os primeiros encontros seriam na capital;
* Isso é uma boa desculpa para se encontrar e tomar um chopp || guaraná || cachaça.
Gostaríamos que as pessoas da comunidade C++ dessem sugestões sobre essa idéia. Estamos pensando em agendar o primeiro encontro para dia 17/12/2005 (sábado) durante a tarde, em um Outback (comida australiana, Shopping Center Norte ou Eldorado, tem infra para crianças e a comida é muito boa). Como pauta do primeiro encontro eu sugiro uma apresentação dos participantes (o que será desnecessário se só eu e o Strauss aparecermos) e uma discussão sobre o presente e o futuro do mercado de trabalho C++.
Coloquem as sugestões nos comentários e quando a gente fechar alguma coisa eu escrevo um novo post com o que definimos. Até lá.
PS: Qualquer semelhança deste post com o conteúdo de um conhecido blog brasileiro sobre programação não é mera coincidência.
Um drama contado em um ritmo adequado, que consegue avançar para um filme de ação em seu terceiro ato de forma surpreendentemente competente, visto que o filme consegue uma identificação com o drama de seus personagens, mesmo que perifericamente, e extrai disso uma emoção maior da perseguição final, pois não estamos assistindo mais um filme de perseguição qualquer.
O uso de câmeras subjetivas, tremidas e visões a la Ultimato Bourne (aéreas dos helicópteros, sons de sirene, trilha crescente) é igualmente competente, especialmente a trilha, que consegue mesclar momentos dramáticos com ação onde quase não percebemos a mudança.
Todas as minhas anotações foi do terceiro, pois é lá que se estabelece como um filme digno de nota. No primeiro e segundo ato, mais morosos, serve exatamente para estabelecer essa identificação com o drama, e pode ser moroso, mas não medíocre, pois nos faz acompanhar com interesse cada momento do plano sendo arquitetado.
O momento mais dramático, quando decidem se irão levar ou não o filho, quando a esposa se joga do carro em movimento, é o mais bem arquitetado nesse sentido de mesclar ação e drama, e prova disso é a trilha sonora, que, quando o casal para no meio da estrada, simplesmente o som que ouvimos é o do ambiente, numa prova irrefutável que a trilha conduz maravilhosamente bem a transição.
Ao mesmo tempo que torcemos pelo protagonista, por termos acompanhado seu plano, este parece verossímil justamente por não ser perfeito, mas por ter tido percalços razoavelmente transpassáveis, como a luta para conseguir um passaporte e dinheiro, ou o fato do plano ter sido jogado no lixo de propósito, em momento de tensão perfeitamente crível, porém, nesse último caso, previsível.
Já não é tão importante no final se ela é culpada ou não, pois sequer nos importamos com isso. Porém, para efeito de conclusão, a última visita ao local do crime tem um caráter simbólico, pois o botão que comprovaria a inocência do réu fica preso na tampa do bueiro, e escapa aos olhos atentos do investigador, igualzinho, da mesma forma com que os fugitivos conseguiram a escapada que parecia impossível.
E se o beijo do filho no final do filme soa piegas, é por pura necessidade de fechar os arcos lançados no decorrer do filme.
# Esse ponteiro vai até onde?
Caloni, 2011-01-17 computer [up] [copy]Brincando com obtenções e conversões de SIDs, tive uma pequena dificuldade de usar a função ConvertStringSidToSid, de Sddl.h. Seu objetivo é receber uma string-SID no formato usado pela ferramenta PsGetSid e retornar uma sequência de bytes de tamanho arbitrário, que é o SID como o sistema o enxerga. Como ela retorna apenas o ponteiro final, do tipo PSID, o que parece fácil pode se tornar tricky se quisermos copiar o SID binário para algum buffer na pilha, já que não sabemos o número de bytes no buffer de origem. Tudo que sabemos é que, após o uso, devemos desalocar essa memória retornada pela API com outra API: LocalFree.
Ora, mesmo que não venhamos a escrever nessa memória de tamanho obscuro, não é de bom tom ler além da conta. Não há garantias que o que estiver após o SID é seguro. Pode até ser o final de uma página de memória, por exemplo, e o seu programa capota por causa de um singelo "Memory could not be read". Que coisa sem graça!
Sempre que me vejo com problemas desse tipo procuro informações primeiro no próprio MSDN, segundo na cabeça e terceiro no Google. Nesse caso em específico a cabeça deu um jeito, pois imaginei que houvesse alguma forma de pegar o tamanho da memória alocada através das funções Local (se a API precisa de LocalFree para desalocar sua memória, é óbvio que ela usou LocalAlloc para alocá-la, mesmo que não tenhamos o código-fonte para comprovar).
A partir de LocalHandle posso obter o HANDLE para a memória alocada localmente. Com esse handle a API me dá outra função, LocalSize, de onde posso obter o tamanho da memória previamente alocada através do seu handle. Isso é ótimo, pois em um primeiro momento pensei não haver saída, como nas funções de alocação em C e C++, por exemplo.
# Atividades extracurriculares
Caloni, 2011-01-18 [up] [copy]Essa é uma resposta a um simpático e-mail de um leitor, o Fabio, me perguntando sobre a tal da lógica (de programação?) e das atividades que um programador pode ter quando está longe do micro para não ficar com a "mente vadiando".
Entusiasta ao máximo, ele montou uma lista baseada em estudo constante sob variadas formas, mesmo longe do micro:
* Contar binário e calcular hexa na cabeça;
* Ler livros;
* Programar em papel;
* Algo mais?
De acordo com ele, o programador não consegue viver sem lógica, e quando tenta, se torna algo "intolerável".
Já fiz duas dessas coisas divertidíssimas em minha tenra idade: contar binário enquanto varria o laboratório onde trabalhava, programar em papel numa noite que fiquei ao relento por ter perdido o busão. Não faço mais essas coisas. Agora eu sou fresco. "Programo em UML".
Primeiro, de que lógica estamos falando? Existem diversas lógicas e existe a intuição, lado importante e muitas vezes renegado, mas presente no cinto de utilidades. É só saber usar. Seja um, seja outro.
Segundo, o cérebro pode cair na vadiagem. Aliás, ele deve. Sem vadiagem, nunca conseguimos processar aquelas threads que ficam rodando em idle, no inconsciente, e que podem resolver uma série de questões que ficam ensebando em nossos conturbados egos. É como o copo cheio de água em Karate Kid (ou em "2012").
O básico mesmo é ler livros. Tão básico que deve ser a atividade principal quando não estamos com nenhum eletrônico bonitinho na mão. Aliás, até quando estamos, com o auto-controle, conseguimos ler um ebook de vez em quando.
Independente do método empregado, nunca visualize seus esforços com ceticismo, e muito menos com o ceticismo dos outros. Se estiver funcionando, continue a fazê-lo. Não vê resultados? Mude o método. Senão cai na velha frase de Eistein sobre o sujeito que espera resultados diferentes fazendo sempre a mesma coisa: loucura.
O que eu adicionaria na lista?
* Assistir CSI. Pra entender o uso prático dos métodos indutivo e dedutivo de raciocínio; mais indutivo.
* Assistir House. Nunca é demais se imaginar como o médico-louco que cura todas as doenças esquisitas; doença aqui é bug.
* Assistir Dexter. Veja como ele faz o seu trabalho seguindo sempre o mesmo método e deixando o ambiente limpinho, sem nenhuma pista.
Fora isso, curta o que está fazendo. Isso é o primordial. Arrebenta com qualquer dúvida que tiver sobre estar no caminho certo.
Ontem fui ver o novo filme de ação de Denzel Washington. É sobre um trem desgovernado e os esforços para segurar o bicho antes que ele destrua alguma coisa. Confesso que fiquei impressionado com a atuação acima de Denzel no papel de Frank, um condutor de trens de carga que trabalhou a vida toda nisso. Seu sotaque e seus gestos condizem de alguma forma com o personagem, enquanto seu companheiro de viagem Will (Chris Pine) fica com seus dramazinhos de família tão bobinhos que passam despercebidos.
Dirigido por Tony Scott, com um currículo considerável (Top Gun, Inimigo do Estado, Deja Vu), o filme logo anuncia ser uma história baseada em fatos reais, e isso parece de alguma forma influenciar a maneira de enfocar a dupla de heróis, com rápidos movimentos de zoom e uma câmera dançante, como que para destacar o clima de urgência, mas por ser exaustivamente repetida, essa técnica torna-se apenas um objeto de distração.
Já o que realmente faz o filme funcionar são as cenas de ação do último ato. Vemos cortes rápidos, mas sincronizados o suficiente para que fiquemos tensos na cadeira a cada movimento novo dos personagens, e, diferente de Transformers 2, aqui conseguimos enxergá-los.
Uma experiência interessante, se você não se importar em esquecer do enredo assim que sair da cadeira do cinema.
Chegando em casa, a Net Movies pegou o denso Munique e deixou no lugar Garotas do Calendário. Triste troca. Uma história que tem como centro um vilarejo na inglaterra em que senhoras de meia-idade posam nus artísticos para um calendário a fim de angariar fundos de caridade mereceria um pano de fundo mais bem tratado. No entanto, o que vemos é uma sucessão de pequenos conflitos que são logo resolvidos e nunca ocupam muito espaço na tela, impossibilitando até mesmo a caracterização das personagens. Onde fica até difícil reconhecer um pouco de ação (como a briga no Conselho das Mulheres que acaba sendo resolvido de forma tão insossa quanto começara) também é difícil reconhecer seu desenlace e a consequente satisfação. Infelizmente, o filme parece realmente ter um ano de duração.
A história clássica de Rapunzel é recriada com o novo senso se humor Disney/Pixar, em que o príncipe é um ladrão procurado, e a frágil princesa não é tão frágil assim. Temos aí os mesmos elementos que tornaram a Disney tão amada pelas crianças e adultos: números de música inspirados (com destaque para o bar do patinho) e uma história sem muitos conflitos e um final feliz.
Uma fotografia aprimorada, que dá a iluminação adequada em todas as cenas (claras e escuras). Uma dublagem duvidosa do príncipe -- versão brasileira --, mas competente dos outros personagens, com destaque para a madrasta da princesa.
Algumas cenas forçadas, que tentam livrar a cara do roteirista que chegou em situações um tanto difíceis de sair: a princesa precisa se lembrar dos seus pais para se livrar de sua madrasta, e as gotas de lágrima dela são curadoras tanto quanto os cabelos.
Destaque para a movimentação dos personagens e suas expressões, uma marca Disney, mas ainda cada vez melhor. A cena dos balões é a mais emocionante, e tem uma equiparação com a da morte do vagalume no trabalho anterior (A Princesa e o Sapo), embora Enrolados seja muito superior em termos de narrativa.
O filme todo gira em torno da história da filha mais velha de uma família problemática que ainda por cima precisa encontrar o pai, pois este afiançou a casa onde moram e, se não comparecer ao tribunal no dia estabelecido, eles serão despejados.
As duas primeiras coisas que sobressaem é a determinação da protagonista e a fotografia sombria, de um azul obscuro, que retrata o clima sem esperanças da jovem batalhadora.
Com muitos diálogos e pouco movimento, a história se desenvolve em cima das descobertas que fazemos a cada nova visita que Ree faz em cada casa vizinha.
Com dois momentos de tensão não muito arrebatadores, somos levados à conclusão da história sob o mesmo clima de desilusão, sendo que, no final das contas, o filme é deprimente do começo ao fim.
O início e no programa do Jô possui um sentido maior por causa da mensagem de que, no final, o lixo de todas as pessoas que assistem a televisão vai parar no mesmo lugar?
A história é sobre um artista plástico famoso por transformar lixo reciclável em obras de arte.
Seu próximo desafio é transformar as pessoas responsáveis por catar esse lixo.
Todo o processo é mostrado desde o início: a primeira visita ao local, o funcionamento da associação de catadores, a vida e o passado dos personagens escolhidos no meio da multidão de pessoas.
Dono de uma visão peculiar sobre toda aquela pobreza, ele próprio nasceu pobre, e aprendeu a manter a lição de que é possível se transformar.
O mais revelador é que assistimos a tudo ainda imaginando o que deverá sair ao final de todo aquele processo, sem entender ainda o efeito artístico sobre aquela vida sem perspectiva das pessoas.
O impacto inicial, da transformação do lixo reciclável em arte usando como modelo as pessoas e a criação de riqueza nesse processo (um dos quadros criados é vendido por cem mil reais).
O impacto final, quando os quadros criados são entregues aos seus respectivos "donos", e a mensagem que fica é imensamente maior que todo o processo: que é possível reciclar pessoas, por piores as condições que elas estejam ou pareçam estar.
# Perfume: A História de um Assassino
Caloni, 2011-01-31 cinema movies [up] [copy]Jean-Baptiste Grenouille é um personagem atípico. Abandonado pela mãe logo após o parto, sua maior (única?) destreza são suas capacidades olfativas: capaz de sentir o cheiro até mesmo de elementos normalmente inodoros como vidro e cobre, e isso nos submete imediatamente ao conceito de fábula, ele segue seu destino tendo como única obsessão na vida criar o perfume perfeito.
Sua trajetória, porém, carrega uma nuvem tenebrosa que paira sobre quem quer que atravesse o seu caminho. Para as pessoas e para o espectador, ele aparece sempre pelos cantos e na penumbra, sorrateiramente, exatamente como os odores que persegue. A fotografia, de pouco contrastre, facilita sua "identificação" nos cenários esquivos construídos para suas principais aparições.
Dotado de pouca sorte, mas ao mesmo tempo de uma persistência inabalável em se manter vivo, Jean-Baptiste não chega a ser um heroi, nem um anti-heroi. Entretanto, se não torcemos por ele, pelo menos, assistindo a seus inescrupulosos atos, encontramos em sua história os motivos que o fazem agir, o que são por si só suficientes para estabelecer uma conexão com o personagem.
Apenas essa "empatia" já seria um feito notável. Entretanto, em seu final catártico, chegamos a visualizar uma nova dimensão criada, aumentando como em uma lupa o significado daquela sociedade histérica e moralmente reprimida. A sensação que fica é que ele é a cura nascida a partir da própria necessidade de se libertar.
Com uma narrativa surreal do começo ao fim, mas que se sustenta em sua coesão interna, ainda que aparentemente a história não chegue a uma conclusão palpável (mas é isso mesmo o que a torna mais notável ainda), percebemos Jean-Baptiste não só como cura daquela sociedade, mas como seu sintoma, e nada mais lógico que o filme volte por onde começou, escancarando a personificação de uma lenda que se foi, mas que uma vez existiu na imaginação das pessoas de uma sinistra época.