Pergunta

Eu tenho uma aula com um método estático que parece mais ou menos:

class X {
    static float getFloat(MyBase& obj) {
        return obj.value();  // MyBase::value() is virtual
    }
};

Estou chamando isso com uma instância de MyDivido que subclasse MyBase:

MyDerived d;
float f = X::getFloat(d);

Se eu vincular o arquivo OBJ contendo x ao meu executável, tudo funciona conforme o esperado. Se estou esperando obter 3,14, entendi.

Se eu criar um .lib que contém o arquivo x.obj e o link no .lib, ele quebra. Quando eu chamo getfloat (), está retornando -1.#Ind00. É esse tipo de valor sentinela que deve me dizer o que há de errado aqui?

Há algo diferente quando você vincula em um LIB em vez de um OBJ diretamente?

Não recebo nenhum aviso ou erros do compilador.

Editar:
Estou usando o Visual Studio 2005 no Windows XP Pro SP3. Para ter certeza de que não estava vinculando arquivos antigos, clonei o método Value () em um novo Método Value2 () e chamei isso. O comportamento era o mesmo.

Editar #2:
Então, se eu rastrear a chamada com meu depurador, estou descobrindo que ele não está entrando no meu método de valor (). Em vez disso, está entrando em um método diferente (não relacionado). Isso me faz pensar que meu vtable está corrompido. Eu acho que o comportamento que estou vendo deve ser um efeito colateral de algum outro problema.


Resolvido! (Obrigado a Vlad)
Acontece que eu estava violando a regra de uma definição (ODR), embora não tenha sido evidente no código que publiquei. este é um ótimo artigo dos caras do Visual C ++ que explica o problema e uma maneira de rastreá -lo. o /D1ReportSingLeclassLayout A bandeira do compilador é uma ferramenta de aprendizado fantástica.

Quando joguei o layout da minha classe para MyBase e Myderived nos dois projetos diferentes, encontrei diferenças entre o código de chamada e o código da biblioteca. Acontece que eu tinha alguns #ifdef blocos nos meus arquivos de cabeçalho e os correspondentes #definir A declaração estava no cabeçalho pré -compilado do projeto principal, mas não no subprojeto (a biblioteca). Eu mencionei o quão mal eu acho que as macros pré -processador são?

De qualquer forma, estou apenas postando essas coisas porque pode ser útil para outra pessoa. Essa questão Também foi muito útil para mim.

Foi útil?

Solução

Este problema ocorrerá quando a lib e o executável forem compilados com diferentes definições do MyDerived classe (ou seja, versões diferentes do .h/.hh/.hpp arquivo que declara MyDerived. Limpe completamente e reconstrua seus projetos. Exceto isso, diferentes opções de compilador poderia Seja responsável, embora seja um pouco improvável.

Se o problema persistir após a reconstrução de tudo do zero, pregue -o instanciando um manequim MyDerived objeto dentro getFloat, na Biblioteca. Use o depurador para comparar o vtable do manequim MyDerived (instanciado na biblioteca) e o vtable do MyDerived A referência de objeto passada como parâmetro (instanciada no executável.) Algo deve aparecer imediatamente.

Outras dicas

Como um LIB é apenas um contêiner, se você está vinculando o mesmo arquivo .OBJ em ambos os casos, como Brian diz que eles não deveriam (não podem?) Ser uma diferença.

Uma coisa a assistir é se você mudou a definição de MyBase, obviamente precisa recompilar a biblioteca e o código usando -a. Por exemplo, se você adicionou um novo método virtual ao MyBase antes do método do valor, isso atrapalharia a biblioteca, pois o deslocamento da tabela em V seria diferente.

Não deve haver diferença. Apenas certifique -se de que os arquivos .h que você esteja incluindo correspondem ao .lib para o qual você está vinculando exatamente. Suspeito que você esteja vinculando a um arquivo .lib antigo.

Se você estiver usando o Visual Studio, em vez de especificar explicitamente o arquivo .lib, basta clicar com o botão direito do mouse no projeto e definir dependências para o projeto .lib. Dessa forma, você terá certeza de que ele usa o arquivo .lib correto.

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