Rodrigo Strauss :: Blog
Bug escabroso no Visual C++ 6.0
Como eu já disse antes, o Visual C++ 6.0 é muito velho e tem sérios problemas para compilar o Boost. E como ficar alocando e desalocando memória na mão é coisa de quem não sabe nada de C++ moderno, meu chefe/gerente criou uma classe de smart pointer com contador de referência para usarmos nos nossos projetos (sim, meu gerente programa e muito bem). Ele me passou a classe para colocar em alguns projetos, e depois de apagar todos os operadores de conversão automática (safety first!), eu encontrei um bug muito estranho no código que usava essa classe.
O que eu consegui isolar é que o bug acontece quando existe um operador de atribuição que é um template. O VC6 se perde completamente, e não gera o código que chama o operador, fazendo com que a atribuição não seja feita e que ele compile um código que é inválido. Eu resumi o código ao menor caso de teste possível, e mudei o nome da classe para CStupidPtr. Bom, vamos ao código:
// // Rode isso no Visual C++ 6.0 e veja o que acontece // template<typename T> class CStupidPtr { T* m_pT; public: CStupidPtr() { m_pT = 0; } template< typename TSrc > CStupidPtr<T>& operator=(const CStupidPtr<TSrc>& p ) throw() { // // vamos colocar um break point forçado aqui para ver // se ele passa // __asm int 3; m_pT = p.m_pT; return( *this ); } public: T* operator->() const throw() { return m_pT; } }; struct TEST { int d; }; int main() { CStupidPtr<TEST> p; // // essa linha NÃO É GERADA PELO VC6, // e não compila em uma versão mais nova do VC, pois é inválida // rode esse programa no debugger do VC6, passo a passo, e você verá // que essa linha é pulada pelo debugger. // p = new TEST(); // // tã! // p->d = 10; return 0; }
Esse código funcionaria se houvesse uma conversão possível de T* para CStupidPtr
Olha que o acontece quando eu compilo esse código no Visual C++ 8:
Microsoft (R) 32-bit C/C++ Optimizing Compiler Version 14.00.50727.42 for 80x86
Copyright (C) Microsoft Corporation. All rights reserved.
vc6_bug.cpp
vc6_bug.cpp(49) : error C2679: binary '=' : no operator found which takes a
right-hand operand of type 'TEST *' (or there is no acceptable conversion)
vc6_bug.cpp(35): could be 'CStupidPtr &CStupidPtr::operator =(const CStupidPtr &)'
with
[
T=TEST
]
while trying to match the argument list '(CStupidPtr, TEST *)'
with
[
T=TEST
]
Pois é, o VC6 já está bem velhinho...
Em 25/11/2005 03:42, por Rodrigo Strauss





Lamentável! Pior que a própria existência de uma função que recebe uma referência const mascara o problema de conversão. Nessas horas até um internal compiler error seria bem-vindo. Tudo menos o silêncio. Parece que foi feito um try-catch em volta desse trecho e o catch ficou quietinho...
Interessante que se usarmos a notação direta o erro vem à tona (apesar de diferente do VC mais novo):
p.operator = ( new TEST() );
error C2784: 'class CStupidPtr<struct TEST> &__thiscall CStupidPtr<struct TEST>::operator =(const class CStupidPtr<T> &)' : could not deduce template argument for 'const class CStupidPtr<`template-param