domingo, 31 de maio de 2009

Funções e expressões Lambda no C++ 0x - Parte 2


Todas as funções lambdas apresentadas no post anterior não possuiam membro de dados. A utilização de membro de dados pode ser feita por meio da captura de variáveis locais que é realizada pelo introdutor lambda ([]). Neste introdutor é possível especificar uma lista de captura (capture-list) como demonstrado no Código 1.

Código 1

int main()
{
vector v;

for (int i = 0; i < 10; ++i)
v.push_back(i);

int x = 0;
int y = 0;

cout << "Input: ";
cin >> x >> y;

v.erase(remove_if(v.begin(), v.end(), [x, y](int n) { return x < n && n < y; }), v.end());

for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });

cout << endl;
}



Um exemplo da execução do programa do Código 1 seria
Input: 4 7
0 1 2 3 4 7 8 9



É importante salientar que apesar do corpo da função lambda estar lexicamente no escopo de main() , ela esta conceitualmente fora do escopo de main(). Sendo assim, não é possível usar variáveis locais declaradas em main() sem “captura-las”.



Todas as capturas são feitas por valor e apenas cópias das variáveis são armazenadas na função. Isso implica em algumas conseqüências importantes: (a) não é possível modificar as cópias capturadas, pois por default a chamada da função objeto é const, (b) atualizações nas variáveis locais não serão refletidas nas cópias capturadas. Mais a frente neste post irei explicar como capturar variáveis por referência.


Ao invés de informar todas as variáveis que deseja capturar, é possível especificar a captura de todas as variáveis locais. A syntax para isso é o introdutor lambda [=]. Usando o exemplo do código 1, bastaria substituir a linha 14 para:


v.erase(remove_if(v.begin(), v.end(), [=](int n) { return x < n && n < y; }), v.end());


Usando este recurso, o compilador irá fazer a captura por valor de todas as variáveis de main() (no exemplo x e y)


Caso seja necessário modificar as variáveis capturadas, pode-se modificar a chamada da função lambda de const para non-const. Para isso deve-se usar o já conhecido modificador mutable. O Código 2 mostra um exemplo deste recurso.

Código 2

int main()
{
vector v;

for (int i = 0; i < 10; ++i)
v.push_back(i);

int x = 1;
int y = 1;

for_each(v.begin(), v.end(), [=](int& r) mutable {
const int old = r;
r *= x * y;
x = y;
y = old;

});

for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });

cout << endl;
cout << x << ", " << y << endl;
}


O exemplo mostrado no Código 2 multiplica cada elemento de v com os 2 elementos anteriores.
Sua execução mostraria
0 0 0 6 24 60 120 210 336 504
1, 1


É importante ressaltar que modificações nas variáveis capturadas não são refletidas nas variáveis locais. Caso seja necessário refletir as modificações das variáveis capturadas sobre suas correspondentes locais, isso é alcançado por meio da captura por referência. A syntax para a captura por referência é o introdutor lambda [&x, &y, &z]. A declaração anterior deve ser lida como referência para x, y e z e não endereço de x, y e z. O Código 3 mostra o Código 2 modificado para usar variáveis capturadas por referência.

Código 3

int main() {

vector v;

for (int i = 0; i < 10; ++i)
v.push_back(i);

int x = 1;
int y = 1;

for_each(v.begin(), v.end(), [&x, &y](int& r) {
const int old = r;
r *= x * y;
x = y;
y = old;
});

for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });

cout << endl;
cout << x << ", " << y << endl;

}


O exemplo mostrado no Código 3 multiplica cada elemento de v com os 2 elementos anteriores.
A execução do Código 3 mostraria
0 0 0 6 24 60 120 210 336 504
8, 9


Observe as diferenças do Código 3 com o Código 2: (i) O introdutor lambda [&x, &y], (ii) a retirada do modificador mutable e (iii) as variáveis locais tendo valores 8 e 9 ao final da execução, refletindo as modificações dentro da função lambda. Também é possível capturar todas as variáveis locais por referência. usando o introdutor lambda [&]

Finaliza aqui o papo sobre funções lambdas. Acho que para um post introdutório o que já foi dito ate aqui é suficiente. Tem muito mais coisas interessantes sobre funções lambdas que não abordei aqui. Para um estudo mais extensivo sobre esta funcionalidade recomendo a leitura da última versão da especificação que pode ser encontrado aqui.

Irei continuar postando sobre o C++ 0x. Percebi que a quantidade de material na língua portuguesa é mínima e irei tentar dar minha contribuição.

[]’s

Leonardo X. T. Cardoso

quarta-feira, 27 de maio de 2009

Funções e expressões Lambda no C++ 0x


Um dos recursos mais importantes do próximo padrão C++ que ainda esta em desenvolvimento é a chamada função lambda.Expressões lambdas definem e constroem implicitamente funções objetos sem nome que na prática se comportam como as já conhecidas funções objetos. Como um trecho de código vale mais do que mil palavras, no Código 1 abaixo pode-se ver a utilização básica de uma função lambda.


Código 1

int main()
{
vector v;

for (int i = 0; i < 10; ++i)
v.push_back(i);

for_each(v.begin(), v.end(), [](int n) { cout << n << " "; });

cout << endl;
}



O [] é chamado introdutor lambda (lambda-introducer) e informa o início de uma função lambda. A declaração do parâmetro lambda é representado por int n e o corpo da função lambda é { cout << n << “ “;. Por default uma função lambda retorna void. Segue abaixo no Código 2 como seria este mesmo código escrito no padrão atual do C++ usando o tradicional funtor.


Código 2


struct Functor {
void operator()(int n) const
{
cout << n << " ";
}

};

int main()
{
vector v;
for (int i = 0; i < 10; ++i)
v.push_back(i);

for_each(v.begin(), v.end(), Functor());

cout << endl;
}


Alguns de vocês já devem estar se perguntando se é permitido colocar vários comandos dentro de uma função lambda. A resposta é sim e um exemplo é mostrado no Código 3:


Código 3


int main()
{
vector v;

for (int i = 0; i < 10; ++i)
v.push_back(i);

for_each(v.begin(), v.end(), [](int n) {
cout << n;
if (n % 2 == 0)
cout << " even ";
else
cout << " odd ";
});

cout << endl;
}



Ao avaliar o Código 3 você já pode estar imaginando a “macarronada” que um programador pode fazer no código ao usar expressões lambda. Se já era fácil fazer códigos ilegíveis agora ficará ainda mais simples. Acredito que em breve vão lançar o Obfuscated C++ 0x Code Contest. Pode ser que criem coisas mais assustadoras do que o já conhecido International Obfuscated C Code Contest (http://www.ioccc.org/).

Antes que você me pergunte, expressões lambdas podem retornar qualquer tipo de dados. Se o corpo de sua função é do tipo { return expr; }, o tipo de retorno será automaticamente deduzido para o tipo de expr. No Código 4 é mostrado um exemplo:


Código 4


int main()
{
vector v;

for (int i = 0; i < 10; ++i)
v.push_back(i);

deque d;

transform(v.begin(), v.end(), front_inserter(d), [](int n) { return n * n * n; });

for_each(d.begin(), d.end(), [](int n) { cout << n << " "; });

cout << endl;
}



No Código 4 o tipo de n*n*n é int e por isso a função lambda retorna int. Lambdas com expressões mais complexas não são capazes de deduzir o tipo de retorno e por isso o programador deve informar explicitamente. O Código 5 ilustra como isso é feito:

Código 5

int main()
{
vector v;

for (int i = 0; i < 10; ++i)
v.push_back(i);

deque d;

transform(v.begin(), v.end(), front_inserter(d), [](int n) -> double {
if (n % 2 == 0)
return n * n * n;
else
return n / 2.0;
});

for_each(d.begin(), d.end(), [](double x) { cout << x << " "; });

cout << endl;
}


O trecho “>- double” é a cláusula opcional de tipo de retorno lambda. O motivo da cláusula não ficar mais a esquerda como acontece com todos os tipos de funções C é que [ ] deve ficar antes para informar ao compilador o início da função lambda. Se o programador não escrever a clausula de tipo de retorno, o compilador provavelmente vai gerar um warning para cada return.

Hoje termino a primeira parte do estudo de expressões lambda. No próximo post irei mostrar expressões lambdas que contem membros de dados.

Referência


O artigo original fonte de inspiração deste post e origem dos código de exemplo pertence ao blog do Visual C++.


[]’s


Leonardo X. T. Cardoso

terça-feira, 26 de maio de 2009

Placa "Live Free or Die" UNIX completa 20 anos

Quem do mundo Unix nunca viu a famosa placa Live Free or Die UNIX em canto pela internet ? Se você nunca viu, segue uma das versões abaixo.


Pois bem, esta placa completou 20 anos em 2009 e foi criada pelo não menos famoso John “Maddog” Hall. Alguns dizem que esta é a placa de carro mais celebrada do estado americano de New Hampshire. Pelo menos no mundo nerd eu não duvido. :)

Segue abaixo uma foto do Maddog ao lado de seu Jeep Wrangler e a placa original.




PS: New Hampshire é um dos poucos estados americanos onde não é cobrado tax. Parece que ele também gosta de fazer suas compras livre de tax. ☺


[]'s

Leonardo X. T. Cardoso

Sun Microsystems anuncia maior App Store do Mundo

De acordo com o CEO da Sun Jonathan Schwarts, a próxima tacada da Sun será a construção de uma App Store que será a maior do mundo deixando a App Store da Apple no chinelo. Esta App Store venderá aplicativos Java com o foco em usuários domésticos. A meta é que o número de usuários ultrapasse 1 bilhão.

Os desenvolvedores vão submeter seus aplicativos no website da App Store e a Sun vai avaliar o conteúdo e segurança antes que seja apresentado ao público. Os ganhos da Sun serão provenientes das taxas de distribuição que serão cobradas de cada aplicativo vendido. Funcionamento parecido com o da App Store da Apple.

O potencial de mercado da Sun é enorme e leva em conta os 4.5 bilhões de computadores, telefones celulares e outros dispositivos que tem suporte Java. Comparando com a App Store da Apple, esta já teve cerca de 1 bilhão de downloads sendo que existem “apenas” cerca de 21 milhões de Iphones em utilização.

Levando em conta estes números, pode ser que a App Store da Sun realmente deixe a da Apple no chinelo em termos de número de usuários e faturamento. Mas isso não será simples e precisará da utilização em massa do serviço pelos usuários de computadores domésticos e smartphones.

Minha opinião é que a Sun pode se dar muito bem se conseguirem construir um bom serviço para downloads de aplicativos para celulares. Lembrando que isso não vai ser fácil dada a variedade de marcas e modelos de aparelhos disponíveis no mercado. Quem já tentou instalar aplicativos escritos em J2ME no celular já percebeu que a idéia de “write once, run anyhwere” não se aplica muito bem. Para usuários de PC eu já acho que o serviço não deve fazer muito sucesso.

E você, o que acha ?

[]’s

Leonardo X. T. Cardoso

Dados sobre o faturamento anual do Firefox

Sempre me perguntei como a fundação Mozilla que é a responsável pelo desenvolvimento do navegador Firefox se mantinha ativa. Como ela ganhava dinheiro para suportar o desenvolvimento do Firefox ? Apesar de muita coisa ser feita de graça por programadores ao redor do mundo, ela possui alguns funcionários e muitos custos fixos de infraestrutura.
Como pagam isso ?

Hoje encontrei um post que esclareceu parte de minhas dúvidas.

Cerca de 85% do faturamento da fundação Mozilla vem de apenas um acordo feito com o Google que garante a bagatela de aproximadamente 57 milhões de doláres anuais.

Para receber este dinheiro basta que a Mozilla mantenha o Google como site de busca default no Firefox. Este acordo vai ate 2011.

Segundo o CEO da Mozilla John Lilly, este dinheiro é usado para pagar funcionários (que são poucos), despesas de hardware/internet, e para distribuição de prêmios.

Mas e ai ? 57 milhões para cobrir os custos não é muita coisa ?
Clicando neste link podemos ver que a quantidade de funcionários é mínima.
Não estou dizendo que alguem esta ficando rico com o navegador, mas tenho curiosidade em saber mais detalhes sobre a contabilidade da fundação.

Alguem ai tem alguma referência ?

[]'s

segunda-feira, 25 de maio de 2009

Workarounds mais ridiculos para bugs em programas

Ontem o slashdot iniciou uma discussão bem interessante sobre os workarounds mais ridículos propostos para a solução temporária de algum bug.

Dois deles são inacreditáveis:

1. Certa vez a Microsoft instruiu seus usuários a mexer continuamente o mouse por vários minutos para que pudessem visualizar os dados provenientes do Oracle no Excel.

2. Recentemente a HP recebeu diversas reclamações de clientes informando que o Office 2007 não era estável em computadores com impressoras HP instaladas. A solução proposta pela HP a seus clientes foi não deixar impressoras HP como a impressora default do sistema. Isso faria com que o Office 2007 funcionasse sem maiores problemas.

E você ? Conhece algum ?

[]'s

Leonardo X. T. Cardoso

Microsoft vai banir o uso da função memcpy

Ainda este ano, a Microsoft irá adicionar as funções memcpy(), CopyMemory(), e RtlCopyMemory() à lista de funções banidas de seu Ciclo de Desenvolvimento Seguro - SDL.

Desenvolvedores que pretendem estar de acordo com as regras do SDL deverão substituir as chamadas de memcpy() para memcpy_s(), que recebe um parâmetro adicional informando o tamanho do buffer para onde os dados serão copiados.
Isso já acontece com outras funções como strcat() e strcpy() que já possuem suas versões seguras strcat_s() e strcpy_s().

[]'s

Leonardo X. T. Cardoso

Implementação da função gettimeofday para Windows

Qualquer programador que algum dia teve ou terá que portar código de algum programa Unix para Windows irá se deparar com diversos trechos de código que dependem da função gettimeofday.

De acordo com o padrão Posix, gettimeofday retorna a hora atual em segundos e microsegundos desde Epoch, armazenando-a na estrutura timeval apontada por tv. Ela sempre retorna 0 e nenhum valor deve ser reservado para indicar erro. (Porque diabos o retorno não é void ?)

Segue abaixo uma implementação para windows originalmente escrita pelo pessoal do OpenAsthra e cujo post original pode ser encontrado aqui.
Apenas a estrutura timezone é definida pois as outras já estão presentes em time.h.


#include

#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
#else
#define DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
#endif

struct timezone
{
int tz_minuteswest; /* minutes W of Greenwich */
int tz_dsttime; /* type of dst correction */
};

int gettimeofday(struct timeval *tv, struct timezone *tz)
{
FILETIME ft;
unsigned __int64 tmpres = 0;
static int tzflag;

if (NULL != tv)
{
GetSystemTimeAsFileTime(&ft);

tmpres |= ft.dwHighDateTime;
tmpres <<= 32;
tmpres |= ft.dwLowDateTime;

/*converting file time to unix epoch*/
tmpres /= 10; /*convert into microseconds*/
tmpres -= DELTA_EPOCH_IN_MICROSECS;
tv->tv_sec = (long)(tmpres / 1000000UL);
tv->tv_usec = (long)(tmpres % 1000000UL);
}

if (NULL != tz)
{
if (!tzflag)
{
_tzset();
tzflag++;
}
tz->tz_minuteswest = _timezone / 60;
tz->tz_dsttime = _daylight;
}

return 0;
}


Para utilizar basta escrever:



struct timeval now;
struct timezone tzone;

gettimeofday(&now, NULL);



[]'s

Leonardo X. T. Cardoso

Palavras-chave: gettimeofday windows

quinta-feira, 14 de maio de 2009

Comando equivalente ao top no Solaris

Quem esta iniciando agora no Solaris ja deve ter percebido que não existe o comando top

Você precisa baixar, compilar e instalar o top a partir do projeto procps.

Mas o Solaris tem um comando equivalente ao top que é o prstat.

Ele possui uma saida similar ao top e pode ser vista na figura abaixo:



O prstat possui diversas flags interessantes que serão assunto de outro post.

[]'s

Leonardo X. T. Cardoso

palavras chaves: top solaris prstat linux

Como habilitar acesso remoto do root com o SSH no Solaris 10

Edite o arquivo

/etc/ssh/sshd_config

Localize a linha
PermitRootLogin no

Troque para
PermitRootLogin yes

Reinicie o sshd.

Pronto, agora você ja pode acessar a máquina como root.

Sparc Sun Blade 100 rodando Solaris 10

Finalmente consegui mexer um pouco com a Blade 100 e instalei o Solaris 10.

Comprei a máquina sem Disco Rígido e fui obrigado a comprar um novo.

Sorte que foram fabricadas para usar componentes de prateleira.

Bastou comprar um Disco IDE e instalar na máquina.

Agora com ela funcionando poderei postar algumas dicas.

Abaixo uma foto que tirei após instalação e inicialização do Solaris 10.

Na outra estação irei instalar Solaris 8 apenas desenvolvimento.
Diversos clientes ainda usam Solaris 8 e 9 e programas "linkados" no Solaris 10 não rodam
nestas plataformas.
Outro dia posto mais detalhes sobre isso.




[]'s

Leonardo

palavras chaves: solaris blade 100

quarta-feira, 13 de maio de 2009

Brincando com uma Itanium 2 de 12 cores.

Segue meu brinquedinho atual na empresa.

A saida real tem outras 11 saidas de processador iguais a esta. Cortei para economizar espaço.

processor : 0
vendor : GenuineIntel
arch : IA-64
family : Itanium 2
model : 0
revision : 4
archrev : 0
features : branchlong, 16-byte atomic ops
cpu number : 0
cpu regs : 4
cpu MHz : 1595.676000
itc MHz : 398.919000
BogoMIPS : 1581.25
siblings : 4
physical id: 6147
core id : 1
thread id : 0

MemTotal: 16587760 kB
MemFree: 16077472 kB
Buffers: 45088 kB
Cached: 184016 kB
SwapCached: 0 kB
Active: 207008 kB
Inactive: 46128 kB
HighTotal: 0 kB
HighFree: 0 kB
LowTotal: 16587760 kB
LowFree: 16077472 kB
SwapTotal: 1048544 kB
SwapFree: 1048544 kB
Dirty: 192 kB
Writeback: 0 kB
Mapped: 38480 kB
Slab: 57072 kB
CommitLimit: 9342416 kB
Committed_AS: 171520 kB
PageTables: 2320 kB
VmallocTotal: 137430493184 kB
VmallocUsed: 4992 kB
VmallocChunk: 137430487136 kB
HugePages_Total: 0
HugePages_Free: 0
Hugepagesize: 262144 kB

Também segue um screenshot dela sendo jugulada pelo gcc.

Usando Calculadora no Spotlight - Mac OS X

Você sabia que o Spotlight tem função calculadora ?

Então..
Basta digitar sua formula no Spotlight que ele faz as contas.

Veja figura abaixo:


[]'s

Leonardo Cardoso

palavras chaves: macosx mac os x calculadora spotlight

Busca instantânea de arquivos no Mac OS X

Um comando muito interessante herdado do Linux pelo Mac OS X é o locate.
Com este comando você pode localizar qualquer arquivo em seu sistema de arquivos de forma instantânea.

Por exemplo, ao executar em minha máquina para o ifconfig tenho a seguinte saida:

lcardoso ~ $ locate ifconfig
/Developer/Documentation/DocSets/com.apple.ADC_Reference_Library.DeveloperTools.docset/Contents/Resources/Documents/documentation/Darwin/Reference/ManPages/man8/ifconfig.8.html
/opt/local/var/macports/sources/rsync.macports.org/release/ports/ruby/rb-ifconfig
/opt/local/var/macports/sources/rsync.macports.org/release/ports/ruby/rb-ifconfig/Portfile
/sbin/ifconfig
/usr/share/man/man8/ifconfig.8.gz
/usr/share/zsh/4.3.4/functions/_ifconfig



Ele usa uma base de dados que contém todos os seus arquivos indexados previamente.
No caso do Mac OS X seu sistema de arquivos é indexado semanalmente por meio do script.
/etc/periodic/weekly/310.locate

Ou seja, no pior caso sua base de dados estará desatualizada em 1 semana.
Mas você pode atualizar a base de dados a qualquer momento executando o script
/usr/libexec/locate.updatedb

Esta operação pode demorar alguns minutos, por isso tenha paciência.

Obs: Não faça isso como root pois iria indexar o sistema de arquivos inteiro mostrando todos os arquivos para qualquer usuário.

[]'s

Leonardo Cardoso

palavras chaves: mac os x locate find buscar localizar

Comando equivalente ao ldd no Mac O SX

Na maioria dos sistemas unix nós usamos o comando ldd para saber quais as dependências de determinado programa. No entanto, ele não esta disponível no Mac OS X.

Outra ferramenta chamata otool provê funcionalidade similar ao ldd.

Veja a saida do seguinte comando:

$ otool -L ffmpeg
ffmpeg:
/usr/lib/libz.1.dylib (compatibility version 1.0.0, current version 1.2.3)
/usr/lib/libbz2.1.0.dylib (compatibility version 1.0.0, current version 1.0.4)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 111.1.3)
/usr/lib/libgcc_s.1.dylib (compatibility version 1.0.0, current version 1.0.0)

Observe pelo manual que o flag -L usado para mostrar as dependências é apenas uma das inúmeras funcionalidades do otool.
Vale a pena dar uma estudada nas outras opções. Quem é desenvolvedor vai precisar delas cedo ou tarde.

[]'s

Leonardo Cardoso

palavras chaves: macosx max os x ldd otool

quarta-feira, 6 de maio de 2009

The remote session was disconnected because there are no terminal server client access licenses available for this computer. Please contact the server

Ontem, ao tentar acessar um servidor recebi a seguinte mensagem:



"The remote session was disconnected because there are no terminal server client access licenses available for this computer. Please contact the server administrator."

Em português parece que esta mensagem foi traduzida da seguinte maneira:

"A sessão remota foi desconectada porque não há licenças de acesso de cliente ao Terminal Server disponíveis para este computador. Contate o administrador do servidor."


A Microsoft tem um artigo falando sobre este problema. Clique aqui para visualizar.

Causa do problema:

- The license server might not have any remaining Per Device CALs to issue.
- Talvez o servidor de licença não tenha mais nenhuma CAL Por Dispositivo para emitir.

Solução do Problema:

-
Use Terminal Server Licensing to determine the number of CALs remaining on the license server. To open Terminal Server Licensing, click Start, Programs, Administrative Tools, and then point to Terminal Server Licensing. If the license server does not have any remaining CALs to issue to clients, purchase and install additional CALs as required.

-
Use o Licenciamento do Terminal Server para determinar o número de CALs restantes no servidor de licença. Para abrir o Licenciamento do Terminal Server, clique em Iniciar, Programas, Ferramentas Administrativas e aponte para Licenciamento do Terminal Server. Se o servidor não tiver mais nenhuma CAL para emitir aos clientes, adquira e instale CALs adicionais, conforme necessário.

Solução Real do Problema:


Para a administração do servidor, estas licensas não são necessárias.

Pode-se executar ate 2 sessões remotas de administração ao mesmo tempo, além da console usando o teclado/mouse. Totalizando ate 3 sessões ao mesmo tempo.

Sendo assim, para resolver esta questão do licenciamento faça o seguinte na estação cliente usada para conectar ao servidor:

1. Fechar o console remoto.
2. Opcionalmente, aconselho a fazer um backup de seu registro.
2. Apagar a seguinte chave de registro:
HKEY_LOCAL_MACHINE\SOFTWARE\MICROSOFT\MSLICENSING

Neste momento você ja pode reiniciar a sessão remota com o servidor.

[]'s

Leonardo Cardoso

Referencias:

http://technet.microsoft.com/pt-br/library/cc756826.aspx
http://technet.microsoft.com/en-us/library/cc756826.aspx
http://www.chat11.com/Remote_Session_Was_Disconnected_Because_There_Are_No_Terminal_Server_Client_Access_Licenses_Available

terça-feira, 5 de maio de 2009

Explicando porque EnumProcessModules retorna ERROR_PARTIAL_COPY - 299 em Windows 64 bits

Semana passada recebi um chamado sobre um problema em um de nossos produtos.

Nosso plugin de monitoração de SQL Server não estava funcionando em Windows Server 2003 64 Bits.

Antes de qualquer coisa, nosso plugin é um programa 32 bits mas executando num ambiente 64 bits usando um mecanismo conhecido como WOW64.

Verifiquei no log do sistema que o plugin não estava conseguindo obter o path do processo do banco de dados (sqlserv.exe).

Para obter o path de um processo usamos a função EnumProcessModules que estava falhando e retornando o erro ERROR_PARTIAL_COPY (erro 299).

Fiz uma breve pesquisa e rapidamente verifiquei que EnumProcessModules não consegue enumerar processos 64 bits a partir de programas 32 bits.

Uma opção era recompilar tudo em 64 Bits. Mas por agora não pretendemos ter 2 builds do mesmo produto.

Descobri que não é apenas este função que tem este problema.

As versões 32 bits das funções EnumProcessModulesEx e GetModuleFileNameEx sofrem do mesmo problema.

Quem quiser mais detalhes técnicos basta clicar aqui.

Solução:

Para windows XP ou superior podemos obter o path de processos 64 bits a partir de programas 32 bits usando a chamada GetProcessImageFileName.

O único problema é que o path retornado tem um formato diferente (/Device/HarddiskVolumeX) do tradicional formato tipo DOS com as letras dos drives no início.

[]'s

Leonardo Cardoso

palavras chaves google: c c++ windows 64 bits win32

sábado, 2 de maio de 2009

Debian Linux na PA-RISC (HP Visualize C3700)

Acabei de terminar a instalação do Debian na PA-RISC.

Instalação trivial.

Não muda nada em relação ao PC/i386.

Basta gravar a imagem no CD, dar o boot e seguir as instruções.
O linux esta rodando perfeitamente com tudo funcionando.

Segue a saida de alguns comandos

$ uname -a
Linux linuxpa 2.6.26-2-parisc #1 Fri Mar 27 03:29:17 UTC 2009 parisc GNU/Linux

$ cat /proc/cpuinfo
processor : 0
cpu family : PA-RISC 2.0
cpu : PA8700 (PCX-W2)
cpu MHz : 750.000000
model : 9000/785/C3700
model name : Allegro W2
hversion : 0x00005dc0
sversion : 0x00000481
I-cache : 768 KB
D-cache : 1536 KB (WB, direct mapped)
ITLB entries : 240
DTLB entries : 240 - shared with ITLB
BTLB : not supported
bogomips : 1495.04
software id : 2005739186


Com isso minha hipótese de hardware ruim esta descartada.

Preciso conseguir outra versão do HP-UX para instalação.

Aguarde cenas dos próximos capítulos.

[]'s

Leonardo Cardoso

Workstation HP Visualize C3700 PA-RISC

Aproveitando o feriado resolvi brincar um pouco com a PA-RISC.

Meu objetivo era instalar o HP-UX e deixar a máquina pronta para futuros trabalhos.

O problema é que ela veio limpa e precisava conseguir uma cópia do HP-UX para instalação.

Fiz uma pesquisa e descobri que a HP disponibiliza cópias gratuitas do HP-UX para fins não comerciais.
As versões recentes do HP-UX são enviadas em cd's gratuitos e as versões mais antigas devem ser copiadas pela internet.

Quem tiver interesse me envie uma mensagem que passo o endereço para requisição junto a HP.

Pois bem, desde início da semana ja tinha feito o download do HP-UX 11.0 que a HP me disponibilizou e estava esperando um tempo livre para instalação.

Ontem com o dia livre tentei a instalação do sistema operacional.

Gravei o primeiro CD no meu MACOSX e ao tentar fazer o BOOT na PA-RISC ela não conseguiu ler o CD. Minha hipótese era de que o drive de CD da PA-RISC é bem antigo e não conseguiu ler o Cd gravado em alta velocidade.

Peguei outro CD virgem e mandei gravar na velocidade mínima.
Com o CD pronto, liguei a PA-RISC, coloquei o CD no drive e pedi para fazer o BOOT.
Tudo OK, a máquina conseguiu dar o BOOT no CD e iniciar o processo de instalação.

Mas alguns instantes depois a instalação morreu com um Page Fault no início da instalação.
Interrupt Type 6 ( Instruction Page Fault)

Clicando aqui você pode ver o erro resultante.

Fiz diversas pesquisas e não encontrei nada a respeito.

Agora estou imaginando se meu hardware esta com problema ou a versão do HP-UX que peguei tem algum BUG ou não contém os patchs apropriados.

Para testar a hipótese de hardware danificado irei tentar instalar o Linux para PA-RISC nele amanhã. Se instalar e rodar OK terei que buscar outras versões de HP-UX para testes.

Leonardo Cardoso