Access Violation

quinta-feira, fevereiro 02, 2006

O que esta errado com este programa (parte iv)?

Antes de mais nada gostaria de explicar: encontrar o problema não é difícil (mesmo assim não vou dizer agora); o mais interessante
é entender porque o mesmo funciona (ou pelo menos, funciona em alguns compiladores).

Vi este programa ao corrigir o trabalho de um dos meus alunos (agora sou um ex-professor :) ). Na época compilei
usando o Borlando C++ 3.0 e funcionou! No VC98 o comportamento muda, mas no Visual Studio 2003 o comportamento foi o mesmo do
Borland C++ 3.0; é claro que o compilador emitiu um aviso (warning) o qual foi ignorado prontamente!

Atenção
Ignorar avisos (warnings) do compilador não é uma prática saudável e eu não recomendo a ninguém fazê-lo! Pelo contrário; analise todas
as warnings geradas em seu código e entenda o porque o compilador esta reclamando. Não assuma que "o compilador possui bugs" muito menos
tome a postura arrogante de achar que sabe mais que o compilador. Se depois de estudar o motivo da warning você concluir que o código que causou
a warning é legítimo, desabilite a warning específica (via #pragma warning) no trecho de código em questão.

O programa recebe um número pela linha de comando e, a seguir, chama uma função para calcular o fatorial deste número.

Bom, vamos ao programa:
0: int fatorial(int n)
1: {
2: if (n == 1)
3: return 1;
4: else
5: n = n * fatorial(n - 1);
6: }
7:
8: int main(int argc, char *argv[])
9: {
10: int n = argc > 1 ? atoi(argv[1]) : 5;
11: int i = fatorial(n);
12:
13: return printf("Farotial(%d): %d", n, i);
14: }



Depois de algum tempo estudando o mesmo entendi porque ele funcionou (mas só vou contar em um post futuro :)).

Abraços.


[+/-] mostrar/esconder este post

terça-feira, janeiro 31, 2006

Oque esta errado com este código (Parte III) : Resposta
Este programa apresenta dois erros comuns relacionados ao desenvolvimento de clientes de componentes COM (é isso ai Daniel, você encontrou os dois!):
  • Utilizar smart pointers no mesmo escopo em que se chama CoInitialize() e CoUninitialize().

  • Tratamento incorreto quando os métodos selectNodes() / selectSingleNode() não retorna nenhum item.
O primeiro problema esta relacionado com o fato de que a chamada a CoUninitialize() será realizada antes do destrutor da classe CComPtr (devido ao
escopo da variável).

Quando o destrutor da classe for executado o método Release() da interface será executado resultando provavelmente em uma exceção (Access Violation).


Como solucionar este problema? Simples, basta declarar a variável em um bloco interno de forma que o mesmo tenha um escopo que termine antes do
escopo da função main().

O segundo problema é que os métodos selectSingleNode() e selectNodes() retornam S_FALSE caso o XPath passado não selecione nenhum nó, ou seja, a expressão da linha 15 será availada como true mas o smart pointer item estará igual a NULL.

Adriano

[+/-] mostrar/esconder este post