Compartilhar via


A pilha de depuração CRT

Este tópico fornece um aspecto detalhado no heap de depuração de CRT.

Neste tópico

Gerenciamento de memória e o heap de depuração

Tipos de blocos no heap de depuração

Recursos do heap de depuração

Usando o heap de depuração

novo, excluir, e _CLIENT_BLOCKs depuração em C++ empilhe

Estado da heap que relata funções

Controlando solicitações de alocação da heap

Gerenciamento de memória e o heap de depuração

Dois dos problemas comuns e de intratáveis que o encontro de programadores está substituindo o final de um buffer atribuído e de vazamentos de memória (não liberam alocações depois que não são necessárias).O heap de depuração fornece ferramentas avançadas para resolver problemas de alocação de memória desse tipo.

As versões de depuração de funções heap chamam o padrão ou as versões de base usadas na versão de compilação.Quando você solicita um bloco de memória, o gerenciador do heap de depuração atribui o heap de base um bloco ligeiramente maior de memória do aplicativo e que retorna um ponteiro para sua parte desse bloco.Por exemplo, suponha que seu aplicativo contém a chamada: malloc( 10 ).Em uma construção de versão, malloc chamaria a rotina de base de alocação da heap que solicita uma alocação de 10 bytes.Em uma construção de depuração, no entanto, malloc chamaria _malloc_dbg, que chamariam a rotina de base de alocação da heap que solicita uma alocação de 10 bytes mais aproximadamente 36 bytes de memória adicional.Todos os blocos de memória resultante no heap de depuração estão conectados em uma única lista vinculada, ordenado de acordo com quando forem atribuídos.

Memória adicional atribuída por rotinas do heap de depuração é usada para informações de contabilidade, para ponteiros que vinculam blocos de memória de depuração juntos, e para buffers pequenos em ambos os lados de seus dados para capturar substitui a região atribuído.

Atualmente, a estrutura de cabeçalho de bloco usada para armazenar informações de contabilidade o heap de depuração é declarada como segue no arquivo de cabeçalho de DBGINT.H:

typedef struct _CrtMemBlockHeader
{
// Pointer to the block allocated just before this one:
    struct _CrtMemBlockHeader *pBlockHeaderNext;
// Pointer to the block allocated just after this one:
    struct _CrtMemBlockHeader *pBlockHeaderPrev;
    char *szFileName;    // File name
    int nLine;           // Line number
    size_t nDataSize;    // Size of user block
    int nBlockUse;       // Type of block
    long lRequest;       // Allocation number
// Buffer just before (lower than) the user's memory:
    unsigned char gap[nNoMansLandSize];
} _CrtMemBlockHeader;

/* In an actual memory block in the debug heap,
 * this structure is followed by:
 *   unsigned char data[nDataSize];
 *   unsigned char anotherGap[nNoMansLandSize];
 */

Os buffers de NoMansLandem ambos os lados da área de dados do usuário do bloco estão atualmente 4 bytes em tamanho, e são preenchidos com um valor conhecido de bytes usado por rotinas do heap de depuração para verificar que os limites do bloco de memória de usuário não são substituídos.O heap de depuração também preenche novos blocos de memória com um valor conhecido.Se você elege para manter blocos liberados na lista vinculada da heap conforme explicado em, esses blocos liberados são preenchidos com um valor também conhecido.Atualmente, os valores reais de bytes são usados como segue:

  • NoMansLand (0xFD)
    Os buffers de “NoMansLand” em ambos os lados de memória usada pelo aplicativo são preenchidos com 0xFD atualmente.

  • Blocos liberados (0xDD)
    Blocos liberados mantidos não usado na lista vinculada do heap de depuração quando o sinalizador de _CRTDBG_DELAY_FREE_MEM_DF é ajustado são preenchidos com 0xDD atualmente.

  • Novos objetos (0xCD)
    Novos objetos são preenchidos com 0xCD quando são atribuídos.

    Neste tópico

Tipos de blocos no heap de depuração

Cada bloco de memória no heap de depuração é atribuído a uma de cinco tipos de alocação.Esses tipos são controlados e relatados de maneira diferente para fins de relatórios de detecção e do estado de escape.Você pode especificar o tipo de um bloco atribuindo o que usa uma chamada direto a uma das funções de alocação da heap de depuração tais como _malloc_dbg.Os cinco tipos de blocos de memória no heap de depuração (definido no membro de nBlockUse estrutura de _CrtMemBlockHeader ) são:

  • _NORMAL_BLOCK
    Uma chamada para malloc ou a calloc cria um bloco normal.Se você pretende usar blocos normais somente, e não tem nenhuma necessidade de blocos de cliente, você pode querer definir _CRTDBG_MAP_ALLOC, que faz com que todos as chamadas de alocação da heap a ser mapeados para seus equivalentes de depuração em compilações de depuração.Isso permitirá o nome de arquivo e número da linha informações sobre cada chamada de alocação a ser armazenado no cabeçalho do bloco correspondente.

  • _CRT_BLOCK
    Blocos de memória atribuídos internamente por muitas funções da biblioteca em tempo de execução são marcados como os blocos de CRT assim que podem ser tratados separadamente.Como resultado, a detecção de escape e outras operações não precisam ser afetadas por eles.Uma alocação nunca deve atribuir, realocar, ou liberar qualquer bloco de tipo de CRT.

  • _CLIENT_BLOCK
    Um aplicativo pode manter a trilha especial de um determinado grupo de alocações para fins de depuração atribuindo as como esse tipo de bloco de memória, usando chamadas explícitos funções de heap de depuração.O MFC, por exemplo, atribui qualquer CObjects como blocos de cliente; outros aplicativos podem manter objetos diferentes de memória em blocos de cliente.Os subtipos de blocos de cliente também podem ser especificados para maior granularidade de rastreamento.Para especificar subtipos de blocos de cliente, deslocar o número à esquerda por 16 bits e por OR ele com _CLIENT_BLOCK.Por exemplo:

    #define MYSUBTYPE 4
    freedbg(pbData, _CLIENT_BLOCK|(MYSUBTYPE<<16));
    

    Uma função de cliente fornecida gancho para despejar objetos armazenados em blocos de cliente pode ser instalado usando _CrtSetDumpClient, e então será chamada sempre que um bloco de cliente é despejado por uma função de depuração.Além disso, _CrtDoForAllClientObjects pode ser usado para chamar uma função determinada fornecida pelo aplicativo para cada bloco de cliente no heap de depuração.

  • _FREE_BLOCK
    Normalmente, os blocos que são liberados são removidos da lista.Para verificar se a liberada memória não está sendo gravada ainda como ou para simular condições de memória baixa, você pode escolher blocos manter liberados na lista vinculada, marcado como livre e preenchido com um valor conhecido byte (momento 0xDD).

  • _IGNORE_BLOCK
    É possível desativar por um período de tempo operações de heap de depuração.Durante este momento, blocos de memória são mantidos na lista, mas marcados como ignoram blocos.

Para determinar o tipo e o subtipo de um bloco determinado, use a função _CrtReportBlockType e macros _BLOCK_TYPE e _BLOCK_SUBTYPE.Macros são definidos em crtdbg.h (), como segue:

#define _BLOCK_TYPE(block)          (block & 0xFFFF)
#define _BLOCK_SUBTYPE(block)       (block >> 16 & 0xFFFF)

Neste tópico

Recursos do heap de depuração

Muitos dos recursos do heap de depuração devem ser acessados do seu código.A seção a seguir descreve alguns dos recursos e como usá-los.

  • _CrtCheckMemory
    Você pode usar uma chamada para _CrtCheckMemory, por exemplo, para verificar em qualquer ponto integridade de heap.Essa função inspeciona cada bloco de memória na heap, verifica que informações de cabeçalho do bloco de memória é válida, e confirma que os buffers não foram alterados.

  • _CrtSetDbgFlag
    Você pode controlar como o heap de depuração se mantém o par de alocações usando um sinalizador interno, _crtDbgFlag, que podem ser lidos e definido usando a função de _CrtSetDbgFlag .Alterando este sinalizador, você pode instruir o heap de depuração para verificar vazamentos de memória quando a saída de programa e relatar todos os escapes que são detectados.Da mesma forma, você pode especificar que blocos de memória liberados para não ser removido da lista vinculada, para simular situações de memória baixa.Quando o heap é verificado, esses blocos são liberados inspecionados em sua totalidade para garantir que não sejam perturbados.

    O sinalizador de _crtDbgFlag contém os seguintes campos de bits:

    Campo de bits

    Padrão

    Valor

    Descrição

    _CRTDBG_ALLOC_MEM_DF

    Ativado

    Alterna a alocação de depuração.Quando esse bit estiver, as alocações permanecem encadeadas mas seu juntos em blocos é _IGNORE_BLOCK.

    _CRTDBG_DELAY_FREE_MEM_DF

    Desativado

    Impede que a memória é liberada na verdade, quanto para simular condições de memória baixa.Quando esse bit estiver ativado, blocos liberados são mantidos na lista vinculada do heap de depuração mas marcados como _FREE_BLOCK e preenchidos com um valor especial de bytes.

    _CRTDBG_CHECK_ALWAYS_DF

    Desativado

    Faz com que _CrtCheckMemory ser chamado em cada alocação e desalocação.Isso diminui a execução, mas os erros de capturas rapidamente.

    _CRTDBG_CHECK_CRT_DF

    Desativado

    Blocos das causas marcados como o tipo _CRT_BLOCK a ser incluído em operações de escape- detecção de estado e diferença.Quando esse bit está, a memória usada internamente pela biblioteca em tempo de execução é ignorada durante essas operações.

    _CRTDBG_LEAK_CHECK_DF

    Desativado

    As causas escapam verificar a ser executado na saída de programa através de uma chamada a _CrtDumpMemoryLeaks.Um relatório de erro é gerado se o aplicativo não liberou qualquer memória que atribuiu.

Neste tópico

Usando o heap de depuração

Quaisquer chamadas para empilhar funções como malloc, free, calloc, realloc, new, e a resolução de delete para depurar versões dessas funções que operam no heap de depuração.Quando você soltar um bloco de memória, o heap de depuração automaticamente verifica a integridade dos buffers em ambos os lados de sua área atribuída e emite um relatório de erros se substituir ocorreu.

Para usar o heap de depuração

  • Vincular a compilação de depuração do aplicativo com uma versão de depuração de biblioteca em tempo de execução de C.

Para alterar um ou mais campos de bits de _crtDbgFlag e criar um novo estado para o sinalizador

  1. Chame _CrtSetDbgFlag com o parâmetro de newFlag definido como _CRTDBG_REPORT_FLAG (para obter o estado atual de _crtDbgFlag ) e armazenar o valor retornado em uma variável temporário.

  2. Ativar todos os bits por OR- ing (bit a bit | símbolo) a variável temporário com máscaras de bits correspondentes (representadas no código do aplicativo por constantes de manifesto).

  3. Desativar os outros bits por AND- ing bit a bit (&) o símbolo variável com NOT bit a bit (~) símbolo máscaras de bits apropriadas.

  4. Chame _CrtSetDbgFlag com o parâmetro de newFlag definido como o valor armazenado na variável temporário para criar o novo estado para _crtDbgFlag.

Por exemplo, as seguintes linhas de código ativam detecção automática de escape e desativam verificar blocos de tipo _CRT_BLOCK:

// Get current flag
int tmpFlag = _CrtSetDbgFlag( _CRTDBG_REPORT_FLAG );

// Turn on leak-checking bit.
tmpFlag |= _CRTDBG_LEAK_CHECK_DF;

// Turn off CRT block checking bit.
tmpFlag &= ~_CRTDBG_CHECK_CRT_DF;

// Set flag to the new value.
_CrtSetDbgFlag( tmpFlag );

novo, excluir, e _CLIENT_BLOCKs depuração em C++ empilhe

As versões de depuração de biblioteca em tempo de execução de contêm As versões de depuração do C++ new e operadores de delete .Se você usar o tipo de alocação de _CLIENT_BLOCK , você deve chamar a versão de depuração do operador de new diretamente ou criar macros que substituem o operador de new no modo de depuração, conforme mostrado no exemplo o seguir:

/* MyDbgNew.h
 Defines global operator new to allocate from
 client blocks
*/

#ifdef _DEBUG
   #define DEBUG_CLIENTBLOCK   new( _CLIENT_BLOCK, __FILE__, __LINE__)
#else
   #define DEBUG_CLIENTBLOCK
#endif // _DEBUG


/* MyApp.cpp
        Use a default workspace for a Console Application to
 *      build a Debug version of this code
*/

#include "crtdbg.h"
#include "mydbgnew.h"

#ifdef _DEBUG
#define new DEBUG_CLIENTBLOCK
#endif

int main( )   {
    char *p1;
    p1 =  new char[40];
    _CrtMemDumpAllObjectsSince( NULL );
}

A versão de depuração dos trabalhos de operador de delete com qualquer bloco tipos e não requer nenhuma alteração em seu programa quando você cria uma versão de lançamento.

Estado da heap que relata funções

_CrtMemState

Para capturar em um determinado momento um instantâneo de resumo de estado da heap, use a estrutura de _CrtMemState definida em CRTDBG.H:

typedef struct _CrtMemState
{
    // Pointer to the most recently allocated block:
    struct _CrtMemBlockHeader * pBlockHeader;
    // A counter for each of the 5 types of block:
    size_t lCounts[_MAX_BLOCKS];
    // Total bytes allocated in each block type:
    size_t lSizes[_MAX_BLOCKS];
    // The most bytes allocated at a time up to now:
    size_t lHighWaterCount;
    // The total bytes allocated at present:
    size_t lTotalCount;
} _CrtMemState;

Essa estrutura salva um ponteiro para o primeiro bloco (recentemente atribuído) na lista vinculada do heap de depuração.Em seguida, em duas matrizes, registra quanto de cada tipo de bloco de memória (_NORMAL_BLOCK, _CLIENT_BLOCK, _FREE_BLOCK, e assim por diante) é na lista e o número de bytes atribuídos em cada tipo de bloco.Finalmente, o registra o número de bytes o maior atribuídos no heap no conjunto até esse ponto, e o número de bytes atribuídos no momento.

Outras funções de relatório do CRT

As seguintes funções informa o estado e o conteúdo da heap, e usam as informações para ajudar a detectar vazamentos de memória e outros problemas.

Função

Descrição

_CrtMemCheckpoint

Salva um instantâneo da heap em uma estrutura de _CrtMemState fornecida pelo aplicativo.

_CrtMemDifference

Compara duas estruturas de estado da memória, salvará a diferença entre eles em uma estrutura do terceiro estado, TRUE e retorna se os dois estados são diferentes.

_CrtMemDumpStatistics

Despeja uma determinada estrutura de _CrtMemState .A estrutura pode conter um instantâneo de estado da heap de depuração em um determinado momento ou a diferença entre dois instantâneos.

_CrtMemDumpAllObjectsSince

Despeja informações sobre todos os objetos atribuídos como um instantâneo determinado foi extraído do heap ou do início de execução.Cada vez que despeja um bloco de _CLIENT_BLOCK , chama uma função de gancho fornecida pelo aplicativo, se ele foi instalado usando _CrtSetDumpClient.

_CrtDumpMemoryLeaks

Determina se qualquer vazamento de memória ocorreu do início da execução do programa e, em caso afirmativo, despeja todos os objetos atribuídos.Cada vez que _CrtDumpMemoryLeaks despeja um bloco de _CLIENT_BLOCK , chama uma função de gancho fornecida pelo aplicativo, se ele foi instalado usando _CrtSetDumpClient.

Neste tópico

Controlando solicitações de alocação da heap

Embora localizar o nome do arquivo de origem e o número da linha em que declarar ou uma macro de relatório executam são geralmente muito útil em localizar a causa do problema, não é o mesmo como provavelmente ser verdadeiro de funções de alocação da heap.Quando macros podem ser inseridos em vários pontos apropriadas na árvore de lógica de um aplicativo, uma enterrada alocação é geralmente em uma rotina especial que é chamado de vários locais diferentes em muitas vezes diferentes.A pergunta não é geralmente o que a linha de código fez uma alocação incorreto, mas em vez que de milhares de alocações feitas por essa linha de código é inválido e como.

Números exclusivas e _crtBreakAlloc de solicitação de alocação

A maneira mais simples para identificar a chamada específico de alocação da heap que foi incorreto for aproveitar o número exclusivo de solicitação de alocação associado com cada bloco no heap de depuração.Quando informações sobre um bloco é relatada por um despejo de funções, esse número de solicitação de alocação é colocado entre chaves (por exemplo, “{36} ").

Uma vez que você souber o número de solicitação de alocação de um bloco incorretamente atribuído, você pode passar este número a _CrtSetBreakAlloc para criar um ponto de interrupção.Interromperá a execução imediatamente antes de atribuir o bloco, e você pode voltar para determinar rotina que era responsável pela chamada incorreto.Para evitar recompilar, você pode executar a mesma coisa no depurador definindo _crtBreakAlloc para o número de solicitação de alocação você está interessado.

Criando versões de depuração de suas rotinas de alocação

Uma abordagem um pouco mais complicada é criar versões de depuração de suas próprias rotinas de alocação, comparáveis para versões de _dbg de funções de alocação da heap.Você pode passar o arquivo de origem e a linha argumento de número adiante para rotinas subjacentes de alocação da heap imediatamente, e você poderá ver onde uma alocação incorreto originou.

Por exemplo, suponha que seu aplicativo contém um similar rotineiro comumente usados ao seguinte:

int addNewRecord(struct RecStruct * prevRecord,
                 int recType, int recAccess)
{
    // ...code omitted through actual allocation... 
    if ((newRec = malloc(recSize)) == NULL)
    // ... rest of routine omitted too ... 
}

Em um arquivo de cabeçalho, você pode adicionar código como o seguinte:

#ifdef _DEBUG
#define  addNewRecord(p, t, a) \
            addNewRecord(p, t, a, __FILE__, __LINE__)
#endif

Em seguida, você pode alterar a alocação em sua rotina de criação registro da seguinte maneira:

int addNewRecord(struct RecStruct *prevRecord,
                int recType, int recAccess
#ifdef _DEBUG
               , const char *srcFile, int srcLine
#endif
    )
{
    /* ... code omitted through actual allocation ... */
    if ((newRec = _malloc_dbg(recSize, _NORMAL_BLOCK,
            srcFile, scrLine)) == NULL)
    /* ... rest of routine omitted too ... */
}

Agora o nome do arquivo de origem e o número da linha onde addNewRecord foi chamado serão armazenados em cada bloco atribuído resultante no heap de depuração e relatados quando esse bloco é examinado.

Neste tópico

Consulte também

Outros recursos

Depurando código nativo

Técnicas de depuração CRT