You are currently browsing Alfredo Kojima’s articles.
Palavras-chave: C, linkagem estática, undefined reference, referência indefinida
Ao linkar programas que usam bibliotecas estáticas que por usa vez usam outras bibliotecas estáticas, pode ocorrer de o linker reclamar da falta de símbolos de uma das bibliotecas, apesar de eles estarem comprovadamente definidos em uma delas. Isso pode ocorrer por causa da ordem errada em que as bibliotecas foram passadas ao linker.
Apesar de o linker se virar para encontrar símbolos em bibliotecas dinâmicas, para as estáticas é necessário passá-las em ordem de dependência. Por exemplo, se seu programa usa a libpng.a que usa a libz.a internamente, o comando correto para linká-lo é:
gcc programa.c -oprograma /usr/lib/libpng.a /usr/lib/libz.a
Mas se a ordem estivesse invertida:
$ gcc programa.c -oprograma /usr/lib/libz.a /usr/lib/libpng.a /usr/lib/libpng.a(png.o): In function `png_reset_crc': undefined reference to `crc32' /usr/lib/libpng.a(png.o): In function `png_calculate_crc': undefined reference to `crc32' /usr/lib/libpng.a(png.o): In function `png_calculate_crc': undefined reference to `crc32' /usr/lib/libpng.a(png.o): In function `png_reset_zstream': undefined reference to `inflateReset' collect2: ld returned 1 exit status
Palavras-chave: C, gcc, cpp, macros, …, varargs, número de parâmetros variável, variadic macros
Para escrever macros de função com número variável de argumentos:
#define DPRINT(fmt, ...) printf("DEBUG: "fmt"\\n", ## __VA_ARGS__)
__VA_ARGS__ será substituído pelos parâmetros dados. E o ## entre a vírgula e __VA_ARGS__ se encarregará de remover a vírgula quando o número de argumentos for 0.
Exemplo:
#include <stdio.h>
#define DPRINT(fmt, ...) printf("DEBUG: "fmt"\\n", ##__VA_ARGS__)
int main()
{
int i= 0, j= 0;
DPRINT("chegou aqui");
DPRINT("valor de i = %i, j = %i", i, j);
return 0;
}
Nota: O Visual C++, a partir da versão 2005, passou a incluir o mesmo recurso.
Palavras-chave: C++, gcc, g++, erro, compilacão, linker, linking
Na maioria dos casos, o erro
undefined reference to `vtable for Class'
ocorre quando falta a definicão de algum método declarado na classe.
Certifique-se que seu Makefile contém o arquivo com a definicão da classe onde ocorreu o erro e que todos os métodos declarados estejam definidos.
Se você quiser mais detalhes sobre o quê causa este erro, leia http://gcc.gnu.org/faq.html#vtables.
Palavras-chave: exceções, gdb, depuração, debug exceptions, catch
Ao depurarmos programas C++ o GDB costuma interromper a execução quando a exceção é pega (catch) ou já quando um signal é lançado e o programa é abortado. O problema é que esse momento é tarde demais para saber o que ocorreu e o stacktrace é inútil. O que queremos é que o GDB faça um break quando a exceção é lançada e para isso usa-se o comando catch throw. O mesmo comando pode ser usado para interromper a execução na captura (catch catch).
Palavras-chave: for, iteração, índice
O for do Python é bastante conveniente para iterar listas, descartando a necessidade de variáveis de índice auxiliares. No entanto as vezes é necessário iterar uma lista e ter o índice de cada elemento além do elemento em si. A forma óbvia é algo como:
for i in range(len(lista)): elem= lista[i] print i, "=", elem
Mas algumas vezes isto pode ser inconveniente (na construção py:for do TurboGears, por exemplo). Nestes casos podemos usar o map() para criar uma lista de tuplas de cada elemento com seu índice:
>>> lista= ["maçã", "banana", "pêra"] >>> for i, elem in map(None, range(len(lista)), lista): >>> print i, "=", elem 0 = maçã 1 = banana 2 = pêra
Atualização: Como comentado pelo Barbieri, a partir do Python 2.3 existe a função enumerate() que faz a mesma coisa:
>>> lista= ["maçã", "banana", "pêra"] >>> for i, elem in enumerate(lista): >>> print i, "=", elem 0 = maçã 1 = banana 2 = pêra
Palavras-chave: C, memória, otimização, arrays, vetores, bitmap, pixmap
Ao se escrever código para manipulação de strings ou imagens, é comum percorrer grandes vetores de bytes. A maneira óbvia de fazer isto é algo no estilo de:
char *ptr= buffer;
for (i= 0; i < fim; i++)
*ptr++= 0;
Mas percorrer memória byte a byte é bastante lento, por questões de alinhamento de memória, o fato dela ser endereçada por palavra. Por exemplo, um int em i386 e long em x86_64.
O exemplo abaixo inclui código que percorre por byte e por int, mas pode ser facilmente modificado para percorrer por longs:
#include <sys/types.h>
int main()
{
char buffer[1000];
uint32_t *iptr;
char *ptr;
int i, j;
int max= 973;
for (j= 0; j < 100000; j++)
{
#ifdef lento
ptr= buffer;
for (i= max-1; i>=0; --i)
*ptr++= 0;
#else
iptr= (uint32_t*)buffer;
// processa o vetor de 4 em 4 bytes,
// arredondando o número de elementos
for (i= max>>2-1; i>=0; --i)
*iptr++= 0;
ptr= iptr;
// processa os últimos bytes restantes
switch (max&((1<<2)-1))
{
case 3: *ptr++= 0; // sem break
case 2: *ptr++= 0; // sem break
case 1: *ptr++= 0;
break;
}
#endif
}
return 0;
}
Os tempos de execução para o código com percorrimento por palavras de 8, 32 e 64bits em uma máquina x86_64, são de: 0.190s, 0.100s e 0.025s, uma melhora de até 800%(!).
Obviamente, neste caso, um memset() seria mais rápido mas o ponto é que este conceito pode ser estendido para casos em que o memset() não serve. Ainda há espaço para mais otimizações, mas isto é deixado como exercício ;)
Obs.: lembre-se que o comprimento de long varia de acordo com a arquitetura e é prudente colocar trechos que dependem disso dentro de #ifdefs.
Leia também um artigo relacionado, sobre o aproveitamento da memória cache nesta dica do Eduardo.
Palavras-chave: OpenGL, Linux, multi-thread, drivers NVidia, crash, segmentation fault, segfault
Se seu programa explode em uma função OpenGL sem nenhum motivo aparente, verifique se a chamada está sendo feita desde a thread onde a OpenGL foi inicializada.
As bibliotecas que vêm com os drivers da NVidia (libGL.so) para X não são muito tolerantes com programas com multi-threading, enquanto a libGL.so da Mesa parece ser mais tolerante a isso. Isso pode levar à confusa situação de o programa rodar sem problemas em alguns sistemas e morrer em outros.
Nos casos em que tive esse problema, o segfault ocorreu na função glViewport(), mas é provável que ocorra com outras funções.
Não existe solucão mágica, mas um workaround — para ao menos testar a hipótese — é mudar o LD_LIBRARY_PATH para apontar ao libGL.so da xorg (se não a tem instalado, tente copiar de outro lugar etc). Verifique se a biblioteca correta está sendo usada com ldd e teste. Já a solucão definitiva é mover as chamadas OpenGL que acessam o mesmo contexto para uma única thread (ou protegê-las com mutexes).
Palavras-chave: C, C++, CPP, macro, string, identificador
Para transformar o nome de um macro ou identificador em string:
#define STR(s) #s
Para transformar o valor de um macro ou identificador em string:
#define STRV(s) STR(s)
O seguinte exemplo ilustra a diferença:
#define STRV(s) STR(s)
#define STR(s) #s
int main()
{
puts("1: "STR(puts));
puts("2: "STR(123));
puts("3: "STR(__LINE__));
puts("4: "STRV(__LINE__));
return 0;
}
Resultado:
1: puts 2: 123 3: __LINE__ 4: 9
Note como STR() retorna um string com o nome do macro, enquanto que STRV() retorna o valor.







Comentários Recentes