Compartilhar via


Declarações

Uma instrução de declaração especifica uma condição que você espera ser verdadeira em um ponto em seu programa.Se a condição não for verdadeira, a declaração falha, a execução do programa é interrompida, e Caixa de diálogo falha de declaração aparece.

Visual C++ suporta instruções de declaração que são baseadas nas compilações:

  • Asserções MFC para programas MFC.

  • ATLASSERT para programas que usam ATL.

  • Declarações de CRT para programas que usam a biblioteca em tempo de execução de C.

  • ANSI declarar a função para outros programas de ++.

Você pode usar declarações para capturar erros lógicos, para verificar os resultados das condições de uma operação, e de erro de teste que deveriam ser tratadas.

Neste tópico

Como funcionam as declarações

Declarações em compilações de depuração e versão

Efeitos colaterais de usar declarações

Declarações de CRT

Asserções MFC

  • MFC ASSERT_VALID e CObject::AssertValid

  • Limitações de AssertValid

Usando asserções

  • A captura de erros lógicos

  • Verificando resultados

  • Localizando erros não tratados

Como funcionam as declarações

Quando o depurador pára devido a um MFC ou declaração de biblioteca em tempo de execução de C, então se a fonte disponível, o depurador navega até o ponto no arquivo de origem onde a declaração ocorreu.A mensagem de declaração aparece na Janela de saída e na caixa de diálogo Falha na asserção.Você pode copiar a mensagem de declaração da janela de Saída a uma janela de texto se você deseja para salvar para a referência futura.A janela de Saída pode conter outras mensagens de erro também.Examine cuidadosamente essas mensagens, pois fornecem indícios a causa de falha de declaração.

Use asserções para detectar erros durante o desenvolvimento.Em geral, use uma declaração para cada suposição.Por exemplo, se você pressupõe que um argumento não é NULO, use uma declaração para testar essa suposição.

Neste tópico

Declarações em compilações de depuração e versão

As instruções de declaração criados somente se _DEBUG é definido.Caso contrário, o compilador trata asserções como instruções nulos.Portanto, as instruções de declaração não impõe nenhum sobrecarga ou custo de desempenho em seu programa de inicialização final, e permitem que você evite usar políticas de #ifdef .

Efeitos colaterais de usar declarações

Quando você adiciona declarações em seu código, certifique-se que as declarações não têm efeitos colaterais.Por exemplo, considere a seguinte declaração que altera o valor de nM :

ASSERT(nM++ > 0); // Don't do this!

Porque a expressão de ASSERT não é avaliada na versão de lançamento do seu programa, nM terá valores diferentes em depuração e versões de lançamento.Para evitar esse problema no MFC, você pode usar a macro de VERIFICAR em vez de ASSERT.VERIFY avalia a expressão em todas as versões mas não verifica o resultado na versão de lançamento.

É especialmente cuidadadoso para sobre como usar chamadas de função em instruções de declaração, como avaliar uma função pode ter efeitos colaterais inesperados.

ASSERT ( myFnctn(0)==1 ) // unsafe if myFnctn has side effects
VERIFY ( myFnctn(0)==1 ) // safe

VERIFY chama myFnctn sobre depuração e versões de lançamento, portanto é aceitável usar.No entanto, usando VERIFY aplica a sobrecarga de uma chamada de função desnecessária na versão de lançamento.

Neste tópico

Declarações de CRT

O arquivo de cabeçalho de CRTDBG.H define macros de _ASSERT e de _ASSERTE para verificar a declaração.

Macro

Resultado

_ASSERT

Se a expressão especificada for avaliada como FALSE, o nome de arquivo e o número da linha _ASSERT.

_ASSERTE

Mesmo que _ASSERT, mais uma representação de cadeia de caracteres de expressão que foi afirmada.

_ASSERTE é mais eficiente porque relata a expressão afirmada que despejou ser FALSA.Isso pode ser o suficiente para identificar o problema sem se referir ao código-fonte.No entanto, a versão de depuração do seu aplicativo conterá uma constante de cadeia de caracteres para cada expressão afirmada usando _ASSERTE.Se você usar muitos de _ASSERTE macros, essas expressões de cadeia de caracteres ocupam uma quantidade significativa de memória.Se os exemplos ser um problema, use _ASSERT para salvar memória.

Quando _DEBUG é definido, a macro de _ASSERTE é definido como segue:

#define _ASSERTE(expr) \
   do { \
      if (!(expr) && (1 == _CrtDbgReport( \
         _CRT_ASSERT, __FILE__, __LINE__, #expr))) \
         _CrtDbgBreak(); \
   } while (0)

Se a expressão avalia a afirmada FALSE, _CrtDbgReport é chamado para relatar a falha de declaração (usando uma caixa de diálogo de mensagem por padrão).Se você escolher Tentar novamente na caixa de diálogo de mensagem, _CrtDbgReport retorna 1 e _CrtDbgBreak chama o depurador com DebugBreak.

ww5t02fa.collapse_all(pt-br,VS.110).gifVerificar danos de heap

O exemplo a seguir usa _CrtCheckMemory para verificar danos de heap:

_ASSERTE(_CrtCheckMemory());

ww5t02fa.collapse_all(pt-br,VS.110).gifVerificando a validade de ponteiro

O exemplo a seguir usa _CrtIsValidPointer para verificar que um determinado intervalo de memória é válido para ler ou gravar.

_ASSERTE(_CrtIsValidPointer( address, size, TRUE );

Os seguintes usa _CrtIsValidHeapPointer de exemplo verificar pontos de um ponteiro para a memória na heap local (criado e o heap gerenciado por esta instância da biblioteca em tempo de execução de C — uma DLL podem ter sua própria instância de biblioteca, e portanto sua própria heap, fora do heap do aplicativo).Essa declaração catch endereços não apenas de zero ou para fora dos limites, mas também ponteiros para variáveis estáticas, a variáveis de pilha, e a qualquer outra memória nonlocal.

_ASSERTE(_CrtIsValidPointer( myData );

ww5t02fa.collapse_all(pt-br,VS.110).gifVerificando um bloco de memória

O exemplo a seguir usa _CrtIsMemoryBlock para verificar que um bloco de memória está no heap local e tem um em blocos válido.

_ASSERTE(_CrtIsMemoryBlock (myData, size, &requestNumber, &filename, &linenumber));

Neste tópico

Asserções MFC

O MFC define a macro de AFIRMAR para verificar a declaração.Também define os métodos de MFC ASSERT_VALID e de CObject::AssertValid para verificar o estado interno de CObjectobjeto derivado de t:system.windows.documents.block.

Se o argumento de macro MFC ASSERT for avaliada como zero ou como false, a macro pára a execução do programa e alerta o usuário; caso contrário, a execução continua.

Quando uma declaração falha, uma caixa de diálogo de mensagem mostra o nome do arquivo de origem e o número da linha da declaração.Se você escolher a nova tentativa na caixa de diálogo, uma chamada a AfxDebugBreak faz com que a execução interrompeu o depurador.Nesse ponto, você pode examinar a pilha de chamadas e usar outras recursos do depurador para determinar como a declaração falhou.Se você tiver habilitado depuração just-in-time, e o depurador não estava sendo executado, a caixa de diálogo pode iniciar o depurador.

O exemplo a seguir mostra como usar ASSERT para verificar o valor de retorno de uma função:

int x = SomeFunc(y);
ASSERT(x >= 0);   //  Assertion fails if x is negative

Você pode usar AFIRMA com a função de IsKindOf para fornecer a verificação de tipo de argumentos de função:

ASSERT( pObject1->IsKindOf( RUNTIME_CLASS( CPerson ) ) );

A macro de ASSERT não produz nenhum código na versão de lançamento.Se você precisar de avaliar a expressão na versão de lançamento, use a macro de VERIFICAR em vez de AFIRMAM.

ww5t02fa.collapse_all(pt-br,VS.110).gifMFC ASSERT_VALID e CObject::AssertValid

O método de CObject::AssertValid fornece verificação de tempo de execução de estado interno de um objeto.Embora não seja necessário substituir AssertValid quando você deriva da classe CObject, você pode fazer sua classe mais confiável fazer isso.AssertValid deve executar declarações em variáveis de membro de qualquer objeto para verificar que contém valores válidos.Por exemplo, deve verificar se os variáveis de membro ponteiro não sejam NULOS.

O exemplo a seguir mostra como declarar uma função de AssertValid :

class CPerson : public CObject
{
protected:
    CString m_strName;
    float   m_salary;
public:
#ifdef _DEBUG
    // Override
    virtual void AssertValid() const;
#endif
    // ...
};

Quando você substituir AssertValid, chame a versão da classe base de AssertValid antes que você execute suas próprias verificações.Use a macro AFIRMAR para verificar os membros da sua classe derivada, como mostrado aqui:

#ifdef _DEBUG
void CPerson::AssertValid() const
{
    // Call inherited AssertValid first.
    CObject::AssertValid();

    // Check CPerson members...
    // Must have a name.
    ASSERT( !m_strName.IsEmpty());
    // Must have an income.
    ASSERT( m_salary > 0 );
}
#endif

Se qualquer um das suas variáveis de membro armazenam objetos, você pode usar a macro de ASSERT_VALID para testar sua validade interna (se suas classes substituem AssertValid).

Por exemplo, considere uma classe CMyData, que armazena CObList em um das suas variáveis de membro.A variável de CObList , m_DataList, armazena uma coleção de objetos CPerson .Uma declaração curta de CMyData tem esta aparência:

class CMyData : public CObject
{
    // Constructor and other members ...
    protected:
        CObList* m_pDataList;
    // Other declarations ...
    public:
#ifdef _DEBUG
        // Override:
        virtual void AssertValid( ) const;
#endif
    // And so on ...
};

Substituição de AssertValid em CMyData tem esta aparência:

#ifdef _DEBUG
void CMyData::AssertValid( ) const
{
    // Call inherited AssertValid.
    CObject::AssertValid( );
    // Check validity of CMyData members.
    ASSERT_VALID( m_pDataList );
    // ...
}
#endif

CMyData usa o mecanismo de AssertValid para testar a validade de objetos armazenados no seu membro de dados.AssertValid substituindo de CMyData chama a macro de ASSERT_VALID para seu próprio variável de membro de m_pDataList.

Teste de validade não param nesse nível porque a classe CObList também substitui AssertValid.Esta substituição realiza teste adicionais de validade no estado interno da lista.Assim, um teste de validade em um objeto de CMyData resulta em testes adicionais de validade para os estados internos do objeto armazenado na lista de CObList .

Com um pouco mais de trabalho, você pode adicionar teste de validade para objetos de CPerson armazenados na lista também.Você pode derivar uma classe CPersonList de CObList e substituir AssertValid.Em uma substituição, você poderia chamar CObject::AssertValid e iterar-o-&z em através da lista, chamando AssertValid em cada objeto de CPerson armazenado na lista.A classe de CPerson mostrada no início deste tópico já substitui AssertValid.

Este é um mecanismo poderosa quando você compila para depuração.Quando você compila posteriormente para a versão, o mecanismo é desativada automaticamente.

ww5t02fa.collapse_all(pt-br,VS.110).gifLimitações de AssertValid

Uma declaração disparada indica que o objeto é definida incorreto e irá interromper a execução.No entanto, uma falta de declaração indica somente que nenhum problema foi encontrado, mas o objeto não é garantido que ele.

Neste tópico

Usando asserções

ww5t02fa.collapse_all(pt-br,VS.110).gifA captura de erros lógicos

Você pode definir uma declaração em uma condição que deve ser verdadeiras de acordo com a lógica do seu programa.A declaração não tem efeito a menos que um erro lógico ocorrer.

Por exemplo, suponha que você esteja simulando moléculas de gás em um contêiner, e numMols variável representa o número total de moléculas.Esse número não pode ser menor que zero, então você pode incluir uma instrução de declaração MFC assim:

ASSERT(numMols >= 0);

Ou você pode incluir uma declaração de CRT como este:

_ASSERT(numMols >= 0);

Essas instruções não fazem nada se seu programa está funcionando corretamente.Se um erro de lógica faz com que numMolsé menor que zero, no entanto, a declaração paralisam a execução do programa e exibem Assertion Failed a caixa de diálogo.

Neste tópico

ww5t02fa.collapse_all(pt-br,VS.110).gifVerificando resultados

As declarações são valiosas para testar as operações cujos resultados não são óbvio de uma inspeção visual rápido.

Por exemplo, considere o código a seguir, que atualiza iMols variável com base no conteúdo da lista vinculada apontada por mols:

/* This code assumes that type has overloaded the != operator
 with const char * 
It also assumes that H2O is somewhere in that linked list. 
Otherwise we'll get an access violation... */
while (mols->type != "H2O")
{
 iMols += mols->num;
 mols = mols->next;
}
ASSERT(iMols<=numMols); // MFC version
_ASSERT(iMols<=numMols); // CRT version

O número de moléculas contadas por iMols sempre deve ser menor ou igual ao número total de moléculas, numMols.A inspeção visual de loop não mostra que este será necessariamente os casos, o que uma instrução de declaração é usada após o loop para testar a condição.

Neste tópico

ww5t02fa.collapse_all(pt-br,VS.110).gifLocalizando erros não tratados

Você pode usar declarações para testar condições de erro em um ponto em seu código onde todos os erros devem ter sido manipulados.No exemplo a seguir, uma rotina gráfica retorna um código de erro ou zero para o êxito.

myErr = myGraphRoutine(a, b);

/* Code to handle errors and
   reset myErr if successful */

ASSERT(!myErr); -- MFC version
_ASSERT(!myErr); -- CRT version

Se o código de tratamento de erros funciona corretamente, o erro deve ser tratado e redefinição de myErr a zero antes da declaração seja alcançado.Se myErr tem outro valor, a declaração falha, o programa pára, e Assertion Failed a caixa de diálogo aparece.

As instruções de declaração não é um substituto para o código de tratamento de erros, no entanto.O exemplo a seguir mostra uma instrução de declaração que pode levar a problemas no código de inicialização final:

myErr = myGraphRoutine(a, b);

/* No Code to handle errors */

ASSERT(!myErr); // Don't do this!
_ASSERT(!myErr); // Don't do this, either!

Esse código depende da instrução de declaração para manipular a condição de erro.Como resultado, qualquer código de erro será retornado por myGraphRoutine não tratados no código de inicialização final.

Neste tópico

Consulte também

Referência

Asserção em código gerenciado

Conceitos

Segurança do depurador

Outros recursos

Depurando código nativo