Pergunta

Eu estou escrevendo uma bastante grande C ++ biblioteca de objeto compartilhado, e ter executado em um pequeno problema que torna a depuração uma dor:

Se eu definir uma função / método em um arquivo de cabeçalho, e se esqueça de criar um esboço para ele (durante o desenvolvimento), desde que eu estou construindo como um objeto biblioteca, em vez de um executável, sem erros aparecem na narração em tempo de compilação me esqueci de implementar essa função. A única maneira de eu descobrir que algo está errado é em tempo de execução, quando, eventualmente, uma aplicação que liga contra esta biblioteca cai com um erro 'indefinido símbolo'.

Eu estou procurando uma maneira fácil de verificar se tenho todos os símbolos que eu preciso em tempo de compilação, talvez algo que eu posso acrescentar ao meu Makefile.

Uma solução que eu vim acima com é para executar a biblioteca compilada através nm -C -U para obter uma lista demangled de todas as referências indefinidas. O problema é este também vem com a lista de todas as referências que estão em outras bibliotecas, como a glibc, que naturalmente será vinculado contra juntamente com esta biblioteca quando a aplicação final é colocar juntos. Seria possível usar a saída do nm para grep através de todos os meus arquivos de cabeçalho e ver se algum dos nomes correspondentes .. mas isso parece insano. Certamente este não é um problema incomum e não há uma maneira melhor de resolver isso?

Foi útil?

Solução

Confira a opção vinculador -z defs / --no-undefined. Ao criar um objeto compartilhado, ele fará com que a ligação falhar se houver símbolos não resolvidos.

Se você estiver usando gcc para invocar o vinculador, você vai usar a opção de compilador -Wl para passar a opção para o vinculador:

gcc -shared ... -Wl,-z,defs

Como um exemplo, considere o seguinte arquivo:

#include <stdio.h>

void forgot_to_define(FILE *fp);

void doit(const char *filename)
{
    FILE *fp = fopen(filename, "r");
    if (fp != NULL)
    {
        forgot_to_define(fp);
        fclose(fp);
    }
}

Agora, se você construir isso em um objeto compartilhado, ele terá êxito:

> gcc -shared -fPIC -o libsilly.so silly.c && echo succeeded || echo failed
succeeded

Mas se você adicionar -z defs, a ligação irá falhar e dizer-lhe sobre o seu símbolo faltando:

> gcc -shared -fPIC -o libsilly.so silly.c -Wl,-z,defs && echo succeeded || echo failed
/tmp/cccIwwbn.o: In function `doit':
silly.c:(.text+0x2c): undefined reference to `forgot_to_define'
collect2: ld returned 1 exit status
failed

Outras dicas

No Linux (que você parece estar usando) ldd -r a.out deve dar-lhe exatamente a resposta que você está procurando.

UPDATE: uma maneira trivial para criar a.out contra o qual a verificar:

 echo "int main() { return 0; }" | g++ -xc++ - ./libMySharedLib.so
 ldd -r ./a.out

Que tal um testsuite? Você cria executáveis ??simulados que apontam para os símbolos que você precisa. Se a ligação falhar, isso significa que a sua biblioteca de interface está incompleta.

Eu tive o mesmo problema de uma vez. Eu estava desenvolvendo um modelo de componente em C ++, e, claro, os componentes deve ser carregado em tempo de execução dinamicamente. Três soluções vêm à mente, que eram os que eu aplicados:

  1. Tire algum tempo para definir um sistema de construção que é capaz de compilar estaticamente. Você vai perder um pouco de engenharia tempo, mas você vai economizar muito tempo captura destes erros de execução irritante.
  2. Grupo seus funções em seções conhecidas e bem compreendidas, de modo que você pode grupo de funções / recibos de ter certeza de que cada função correspondente tem o seu topo. Se você tomar o tempo em documentar-lo bem, você pode escrever, talvez um script que verifica as definições (através, por exemplo, as suas observações doxygen) e verifique o arquivo .cpp correspondendo por isso.
  3. Faça vários executáveis ??de teste que carregar o mesmo conjunto de bibliotecas e especifique o sinalizador RTLD_NOW para dlopen (se você estiver sob * NIX). Eles irão sinalizar os símbolos que faltam.

Espero que ajude.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top