×
Namespaces

Variants
Actions
(Difference between revisions)

Abandonos (Leaves)

From Nokia Developer Wiki
Jump to: navigation, search
cabezonxdg (Talk | contribs)
m
cabezonxdg (Talk | contribs)
(O artigo anterior estava muito vago.)
Line 1: Line 1:
O SymbianOS foi desenhado para trabalhar em dispositivos portáteis com limitações de recursos (principalmente memória). Tais dispositivos devem ser capazes de funcionar por longas horas (ou até mesmo semanas) sem a necessidade de um ''reboot''. Para que isso seja possível o SymbianOS implementa um sistema de tratamento de exceções e gerência de recursos bastante eficiente, chamados de abandono. Abandonos (''leaves'') podem ser comparados ao sistema de exceções encontrado em C++. Abandonos podem ocorrer como resultado de uma condição de erro ou de um evento anormal, como falta de memória ou de espaço em disco (ou falta de espaço no cartão de memória flash) para completar uma operação. O abandono propaga o erro a um local no código onde ele pode ser gerenciado, chamado TRAP harness.<br>
+
== Introdução ==
 +
Um código em Symbian é dito que abandona quando um erro em tempo de execução ocorre. Abandonos fazem parte do mecanismo próprio de exceção implementado pelo c++ para Symbian OS, eles seriam análogos ao <tt>throw</tt> de c++ padrão e são utilizados no lançamento de exceções.  
  
== TRAP Harness ==
+
Segundo a conveção de nomes adotada pelo SymbianC++ funções que abandonam tem seu nome terminado por L indicando ao quem usá-las que tal função pode abandonar. Uma função ao abandonar emite um código de erro indicando o motivo pelo qual a operação falhou.
  
Para contornar a falta do sistema de exceção padrão foram desenvolvidas as funções ''TRAP'' e ''TRAPD'' que podem ser consideradas como alternativas ao Try/Catch (apesar de sua implementação interna no Symbian v9.0 ser feita utilizando Try/Catch). Na ocorrência de um abandono , ele será propagado até que seja capturado por uma TRAP. Caso a TRAP não seja implementada pelo programador o abandono será capturado pelo TRAP do FrameWork e o SO irá tomar as precauções necessárias (exibir uma dialog com o motivo do abandono por exemplo). No entando em algumas ocasiões o programador necessita gerenciar de forma particular um abandono e então fazemos o uso da função TRAP.<br>
+
Funções podem abandonar se:
  
TRAPS são macros definidas no cabeçalho e32cmn.h<br>
+
* Fizerem chamadas a outras funções que abandonam fora de uma <tt>TRAP</tt>;
 
+
* Chamando uma das funções do sistema utilizadas para lançar abandonos, exemplo: <tt>User::Leave()</tt>;
 
+
* Fizerem uso do operador sobrecarregado <tt>new</tt>.
<code cpp="cpp">TRAP(_r, _s);</code>
+
 
+
 
+
 
+
 
+
TRAP(_r, _s);
+
 
+
Esta função executa um conjunto de instruções C++ e retorna um inteiro com o valor do abandono (caso tenha ocorrido).<br>
+
 
+
Onde:<br>
+
 
+
_r = O código de abandono gerado pelas funções é salvo neste inteiro. Este inteiro precisa ser declarado antes de usar a TRAP.<br>
+
 
+
_s = Conjunto de instruções C++ que serão colocadas "a prova" utilizando a TRAP. Caso estas abandonem o valor é passado para _r.
+
 
+
Uma alternativa à TRAP é o TRAPD, utilizado apenas por conveniência onde o inteiro que recebe o código de abandono não precisa ser declaro explicitamente.
+
 
+
<br>
+
 
+
Exemplos de uso do TRAP:<br>
+
<code cpp="cpp">TInt err;
+
TRAP(err, FuncaoQuePodeAbandonarL());
+
if( err == KErrNone ) // não ocorreu abandono
+
{
+
      // faz algo
+
}
+
else // Ocorreu abandono
+
{
+
        // faz algo
+
}</code>
+
Exemplo com TRAPD:
+
<code cpp="cpp">TRAPD(err, FuncaoQuePodeAbandonarL());
+
if( err == KErrorNone )
+
{
+
        // faz algo
+
}
+
else
+
{
+
        // faz algo
+
}</code>
+
 
+
 
+
<br> <br> '''Nota:''' A utilização de TRAPS na aplicação aumenta significamente o tamanho do código final e causa um certo overhead, então deve ser utilizado com cautela.
+
 
+
== Pilha de limpeza ==
+
 
+
Considere o seguinte código:<br>
+
<code cpp="cpp">void CMinhaClasse::CarregarAlgoL()
+
{
+
        CCarro* fiat = new (ELeave) CCarro();
+
        fiat->DirigirL();
+
        delete fiat;
+
}
+
</code>
+
 
+
 
+
<br> <br> É feita a alocação dinâmica de um objeto do tipo CCarro e então este objeto chama o método DirigirL. Este método pode lançar uma exceção - ''Métodos que possam lançar exceção terminam com L'' - , caso uma exceção ocorra todas as variáveis automáticas do método CarregarAlgoL serão removidas incluindo neste caso o ponteiro fiat. Isto acontecendo perderemos a referência para a memória que fiat aponta - ''quando ocorre uma exceção não há garantia que o destrutor da classe será chamado ou que os códigos seguintes serão executados''-&nbsp; no exemplo, o comando delete nunca será executado. O resultado seria um vazamento de memória. Pode parecer que alguns bytes não representam muita coisa, mas para um sistema com recursos limitados e que não faz re-boot frequentemente isto pode ocasionar sérios problemas.<br>
+
 
+
Para resolver problemas como este foi desenvolvido o mecanismo de limpeza da pilha ( CleanupStack ). Considere o seguinte código:<br>
+
 
+
<br>
+
<code cpp="cpp">void CMinhaClasse::CarregarAlgoL()
+
{
+
        CCarro* fiat = new (ELeave) CCarro();
+
        CleanupStack::PushL( fiat );
+
        fiat->DirigirL();
+
        CleanupStack::PopAndDestroy();
+
}</code>  
+
<br>Caso não tenha notado, foram adicionadas duas linhas de código que representam chamadas à métodos de CleanupStack. Neste código, caso DirigirL abandone não perderemos a referência a memória que fiat aponta. Seu uso é bastante simples, você adiciona ponteiros automáticos à pilha e na ocorrência de um abandono será chamado o destrutor do objeto que este ponteiro aponta e então sua memória será liberada através do operador User::Free.
+
 
+
 
+
 
+
<br>
+
 
+
A classe CleanupStack possui apenas&nbsp; 4 métodos (com suas devidas sobrecargas) todos são estáticos e bastante intuítivos.<br>
+
 
+
'''PushL'''- Adiciona um ponteiro a pilha de limpeza.
+
 
+
'''Pop'''- Remove um ponteiro da pilha de limpeza
+
 
+
'''PopAndDestroy'''- Remove um ponteiro da pilha de limpeza e libera sua memória. O mesmo que realizar um CleanupStack::Pop() e então delete.
+
 
+
<br>
+
 
+
'''''Nota 1''''': PushL pode gerar um abandono mas está fora do escopo deste artigo discutir isto, para maior informações consulte [1].
+
 
+
'''''Nota 2''''': Atributos membros de classe não devem ser adicionados a pilha de limpeza pois é função da sua classe realizar a deleção. Sendo colocado na pilha de limpeza poderia ocorrer uma dupla deleção o que pode ocasionar problemas.
+
 
+
== Construção em duas fases ==
+
 
+
Construtores e destrutores não podem retornar um valor e por isso não pode abandonar. Pensando nisso, foi desenvolvido a contrução em duas fases para evitar que construtores gerem abandonos. Funções que possam gerar um abandono devem ser chamadas no ConstructL (L no final é uma convenção de nome que significa que essa função pode abandonar) ao invés do construtor padrão C++. Qualquer outra inicialização que não possa abandonar pode ser inicializada normalmente no construtor padrão.
+
 
+
Exemplo:
+
 
+
<br>
+
<code cpp="cpp">void CMinhaAplicao::ConstructL(const TRect& aRect)
+
{
+
    CMinhaAplicacao* self = CMinhaAplicacao(aRect);
+
    CleanupStack::PushL(self);
+
    self->ConstructL(aRect) ;
+
    CleanupStack::Pop(self);
+
    return self;
+
}
+
 
+
CMinhaAplicacao::CMinhaAplicacao()
+
{
+
    iVariavel = 1;
+
}
+
</code>
+
 
+
 
+
<br> <br>
+
 
+
== Leitura complementar ==
+
 
+
[[Pilha de limpeza - Cleanup Stack|[1] - Pilha de limpeza - Cleanup Stack]]<br> [[Construtor em 2 fases]]<br> [[Gerência de memória]]<br>
+
 
+
[[Category:Lang-PT]] [[Category:Symbian_C++_(Português)]]
+

Revision as of 21:24, 5 September 2009

Introdução

Um código em Symbian é dito que abandona quando um erro em tempo de execução ocorre. Abandonos fazem parte do mecanismo próprio de exceção implementado pelo c++ para Symbian OS, eles seriam análogos ao throw de c++ padrão e são utilizados no lançamento de exceções.

Segundo a conveção de nomes adotada pelo SymbianC++ funções que abandonam tem seu nome terminado por L indicando ao quem usá-las que tal função pode abandonar. Uma função ao abandonar emite um código de erro indicando o motivo pelo qual a operação falhou.

Funções podem abandonar se:

  • Fizerem chamadas a outras funções que abandonam fora de uma TRAP;
  • Chamando uma das funções do sistema utilizadas para lançar abandonos, exemplo: User::Leave();
  • Fizerem uso do operador sobrecarregado new.
128 page views in the last 30 days.
×