Pular para o conteúdo principal

Postagens

Mostrando postagens com o rótulo cxx

Construindo um "cross toolchain" com GCC 5.1 e binutils 2.25

Uma das Pesquisas no Laboratório investiga o uso de C++ moderno (inicialmente 2011, agora 2014) na definição de programas bare metal. Nosso interesse geral está em aplicações de I/O e um dos nossos interesses específicos está em aplicações tipo "dispositivo criptográfico". Ao retornar para esta Pesquisa, resolvemos atualizar nossas ferramentas para obter uma implementação completa do C++ 2014. Nossa motivação foi o lançamento do GCC 5.1 que inclui suporte completo para esta nova especificação. Nosso objetivo é estudar aplicações para BIOS, UEFI, Multiboot 1 e 2 e outras "máquinas" similares emuladas com qemu. Estamos construindo programas para arquitetura i686-pc-elf . Nosso ambiente de desenvolvimento é Fedora 21 64 bits, onde as ferramentas tem arquitura alvo x86_64-redhat-linux . Apesar de x86_64 e i686 serem "compatíveis", nesse tipo de projeto é necessário um cross toolchain. Precisamos basicamente de um cross binutils e um cross g++. Existem di...

Pela milionésima vez este erro

Cometi pela milionésima vez o mesmo erro e deixo este artículo na tentativa de impedir a próxima: não, não interessa se a operação overlapped diz que completou imediatamente, haverá uma completion packet esperando na completion port . Apenas ignore.

Porting C to ... C

Chegou, então, a hora de ressuscitar um programa desenvolvido pelo fundador da empresa em um inominável sistema UNIX rodando em i386 no passado remoto. O programa, cujo sistema de construção permitia a configuração para inúmeras variantes do UNIX de então, permaneceu compilável com mínimas modificações até o Fedora 17. Impressionante. Infelizmente, ao executar o programa, segmentation fault a torto e a direito. Com a ajuda de um debugger , alcançamos a seguinte iteração, simplificada para este artigo: for (int i = 0; i < name_list_size; ++i) {   p = (char *) getenv(name_list[i]);   if (p != NULL)     if (*p != NULL)       strcpy(value_list[i], name_list[i]); } Simples, certo? O programa levantava SIGSEGV ao avaliar a expressão *p . Como é possível? Certamente getenv retorna um endereço válido ou NULL . Certamente p não é NULL quando avalia-se *p . Qual é o tipo de p ? char * p . Por acaso o programa está s...

Servidor e usuário COM na mesma "solution"

 Um dos objetivos da próxima iteração no meu projeto atual é quebrar o sistema em mais pedaços, e levantar os pedaços um nível de abstração até componentes COM. Uma das consequências é substituir diversas ligações mais estáticas e torná-las ligações mais dinâmicas através do COM. Tipicamente, um programa usuário de um componente COM, escrito para o Visual Studio, usará a diretiva #import para incluir na unidade de tradução C++ as declarações necessárias. Isso implica que o componente deve estar instalado na máquina que constrói o programa. O que fazer quando o componente em questão está no mesmo lote de construção que o programa usuário? A solução inicial é criar uma dependência de construção tal que o componente seja sempre construído primeiro, e usar um post-build event ao projeto do componente para registrá-lo no sistema. Desse modo, na construção do programa, o ambiente estará correto. Eu considero este arranjo prejudicial. Minha melhor razão é esta: o servidor de const...

Visual Studio 6: debugger vs. Unicode string

Gente, depois de uma eternidade de sofrimento para interpretar (TCHAR *) no debugger do Visual Studio 6, eu acabei de descobrir, nesse minuto!, que existe uma opção chamada "Display Unicode String" e que esta opção não está marcada na configuração padrão . Em Options, Debug. Você clica nela e o debugger mostra strings de wchar_t. Por quê!?

Análise Sintática Incremental

Em 2008, perguntei na ccppbrasil.org sobre uma boa maneira de produzir parsers incrementais. Dois anos depois, pude parar e estudar o manual do Bison o suficiente para descobrir ali o meu objetivo: push parsers . Este exemplo do manual é precisamente o que eu quero: int status; yypstate *ps = yypstate_new (); do { status = yypush_parse (ps, yylex (), NULL); } while (status == YYPUSH_MORE); yypstate_delete (ps); Meu objetivo é aplicar esta técnica para produzir o decodificador de mensagens de protocolo de aplicação em um servidor baseado em readiness-notification e non-blocking I/O.

Por que goto é considerado prejudicial?

Recentemente, o Fabiano Vasconcelos abriu uma discussão no Grupo de Usuários de C e C++: De cara eu vi algo aqui um pouco estranho, se que o amigo Márcio me permite comentar: que muitos programadores, inclusive eu (se que posso ser rotulado como programador) foram instruídos com o princípio de NUNCA usar o goto, por ser considerado um mau estilo de programação. Durante a discussão, o Eduardo Vieira puxou um artigo da KernelTrap sobre uma discussão similar ocorrida no grupo de desenvolvimento do Linux, onde Robert Wilken disse o seguinte: In general, if you can structure your code properly, you should never need a goto, and if you don't need a goto you shouldn't use it. It's just "common sense" as I've always been taught. Unless you're intentionally trying to write code that's harder for others to read. É preciso colocar a máxima "goto considered harmful" na perspectiva histórica adequada. Acredito que praticamente todo programador trein...

Test Driven em C++ cross-compiled é possível

afe! Enquanto não rola um estudo retrospectivo maneiro, aqui vão minhas primeiras impressões. por mais que pareça andar de ré, tenha um porting para o sistema do desenvolvedor, onde a compilação não é cruzada; não exija frameworks xUnit e faça bilhões de programecos se necessário; guarde no coração que não é preciso reflection nem mesmo shared objects para aplicar dependency injection; não despreze a tediosa tarefa de testar parte a parte, pequena parte a pequena parte; não tenha escrúpulos para satisfazer dependências aleatórias com stubs. A maior revelação para mim nesse processo foram os pontos 2, 3 e 5 acima. Após um longo tempo digerindo o problema, e após diversas discussões sobre que framework de testes usar, por fim completei a tarefa da forma mais tosca possível: cada teste é um programa executável individual.  O projeto usa cmake para configurar a construção, e o ctest funciona legal com essa lista de programas de teste. O maior esforço nesse processo foi refat...

C++0x vai mudar sua vida: listas de inicialização

Com a nova sintaxe para listas de inicialização, é como se agora houvesse uma notação para o valor literal de praticamente qualquer estrutura de dados. Observe meu teste de unidade construindo um "attribute template" PKCS #11 com std::vector direto na inicialização: std::vector attributes {   CK_ATTRIBUTE { CKA_CLASS, &object_class, sizeof(object_class) },   CK_ATTRIBUTE { CKA_TOKEN, &on_token, sizeof(on_token) },   CK_ATTRIBUTE { CKA_LABEL, &label, sizeof(label) },   CK_ATTRIBUTE { CKA_APPLICATION, &application, sizeof(application) },   CK_ATTRIBUTE { CKA_VALUE, &data, sizeof(data) } }; O segredo da notação está nessa pseudo-gramática:   type-name identifier { initializer-list }; que é análoga em significado a:   type-name identifier ( argument-list ); ou:   type-name identifier = type-name ( argument-list );