Pergunta

Eu estou tentando adicionar melhorias a um velho ++ programa VC 6.0 de 4 anos. A compilação de depuração é executado a partir da linha de comando, mas não no depurador: ele trava com um printf violação de acesso dentro (). Se eu pular o printf, então ele trava em malloc () (chamado de dentro fopen ()) e eu não posso ignorar isso.

Isso significa que eu não pode ser executado no depurador e têm de confiar nas velhas declarações printf para ver o que está acontecendo. Isto, obviamente, faz com que seja muito mais difícil.

Qualquer idéia porque printf () e malloc () iria falhar quando executado no depurador do VC ++? Eu não sou bom neste tipo de coisas de baixo nível!

Aqui está a pilha de chamada após a violação de acesso:

_heap_alloc_dbg(unsigned int 24, int 2, const char * 0x0046b3d8 `string', int 225) line 394 + 8 bytes
_nh_malloc_dbg(unsigned int 24, int 0, int 2, const char * 0x0046b3d8 `string', int 225) line 242 + 21 bytes
_malloc_dbg(unsigned int 24, int 2, const char * 0x0046b3d8 `string', int 225) line 163 + 27 bytes
_lock(int 2) line 225 + 19 bytes
_getstream() line 55 + 7 bytes
_fsopen(const char * 0x00468000 `string', const char * 0x00466280 `string', int 64) line 61 + 5 bytes
fopen(const char * 0x00468000 `string', const char * 0x00466280 `string') line 104 + 15 bytes
open_new_log(const char * 0x00468000 `string') line 66 + 14 bytes
log_open(const char * 0x00468000 `string', int 0) line 106 + 9 bytes
Xlog_open(const char * 0x00468000 `string', int 0) line 51 + 13 bytes
service_start(unsigned long 1, char * * 0x009a0e50) line 3152 + 12 bytes
service_init2(char * 0x00471fcc char * NTPROGRAM, char * 0x004723c4 char * NTSERVICE, char * 0x00466540 `string', unsigned long 1, char * * 0x009a0e50) line 508 + 13 bytes
service_init(char * 0x00471fcc char * NTPROGRAM, char * 0x004723c4 char * NTSERVICE, unsigned long 2, char * * 0x009a0e50) line 548
main(unsigned long 2, char * * 0x009a0e50) line 3131
mainCRTStartup() line 206 + 25 bytes
KERNEL32! 7c817067()

Aqui está a depuração desmontagem até a operação que falha:

0041EA7E   jmp         _heap_alloc_dbg+2B3h (0041eb23)
0041EA83   mov         edx,dword ptr [_lTotalAlloc (004b4294)]
0041EA89   add         edx,dword ptr [nSize]
0041EA8C   mov         dword ptr [_lTotalAlloc (004b4294)],edx
0041EA92   mov         eax,[_lCurAlloc (004b429c)]
0041EA97   add         eax,dword ptr [nSize]
0041EA9A   mov         [_lCurAlloc (004b429c)],eax
0041EA9F   mov         ecx,dword ptr [_lCurAlloc (004b429c)]
0041EAA5   cmp         ecx,dword ptr [_lMaxAlloc (004b42a0)]
0041EAAB   jbe         _heap_alloc_dbg+249h (0041eab9)
0041EAAD   mov         edx,dword ptr [_lCurAlloc (004b429c)]
0041EAB3   mov         dword ptr [_lMaxAlloc (004b42a0)],edx
0041EAB9   cmp         dword ptr [_pFirstBlock (004b4298)],0
0041EAC0   je          _heap_alloc_dbg+25Fh (0041eacf)
0041EAC2   mov         eax,[_pFirstBlock (004b4298)]
0041EAC7   mov         ecx,dword ptr [pHead]
0041EACA   mov         dword ptr [eax+4],ecx

Aqui é a nossa fonte para que as chamadas de fopen () e falha no malloc ()

FILE *open_new_log( const char *logfile )
{
    FILE *fp;
    int retry = 0;

    while( ( fp = fopen( logfile, "w" ) ) == NULL && ++retry < 300 )
        Sleep( 1000 );

    return( fp );
}

O erro que eu vejo é

Unhandled exception inPISCOOP.exe: 0xC00000005: Access Violation

Saudações,

--- Alistair.

Foi útil?

Solução

Você pode usar _CrtSetDbgFlag() para ativar um grupo de técnicas montão de depuração úteis. Há uma série de outras funções CRT depuração disponíveis que deve ajudá-lo a rastrear onde o seu problema.

Outras dicas

Quando executado a partir do depurador, uma pilha diferente é usado; este é referido como o depuração pilha . Isto tem um comportamento diferente da pilha usada fora do depurador, e está lá para ajudá-lo a detectar os problemas como este.

Note que o Win32 "pilha de depuração" é distinto do VC ++ "pilha de depuração"; ambos têm a intenção de fazer mais ou menos a mesma coisa, no entanto. Consulte este artigo que descreve a diferença no comportamento quando você executar o aplicativo sob o depurador.

Neste caso, você provavelmente corrompido a pilha antes de chamar esta função, quer por escrito fora da final ou desligar o início de um bloco de heap.

O mais fácil de abordagens (desde que a sua aplicação não está usando memória também extensivamente) é para permitir verificação pilha de página inteira (que vai colocar chamado página de proteção após a página de memória sua alocação é fornecida a partir, o que, por sua vez, identificar o local exato em seu código onde a corrupção ocorre).

Uma vez que você tem ferramentas de depuração do Windows acessível, execute o comando a seguir gflags para configurar pilha de página inteira:

gflags[.exe] /p /enable yourapp.exe /full

Nota, você deve fornecer o nome executável (ou seja, sem prefixo do caminho!)
Em seguida, basta executá-lo sob o depurador - ele vai quebrar com a primeira tentativa de corromper o heap. A diferença aqui é que corrupções de pilha são defeitos maioritariamente adiado que se manifestam mais tarde, quando um (possivelmente) a operação pilha válida está em vigor.

Note, também:

gflags[.exe] /p /enable yourapp.exe /full /backwards

, adicionalmente, coloque uma página de proteção antes de sua alocação.

Running switch com / p sozinho irá exibir as opções da página heap atualmente em vigor.

Você pode ter um bug corrupção de pilha. Sua aplicação pode ter corrompido a pilha antes open_new_log() é chamado.

Eu jmattias suspeitos é certo. A causa raiz do problema é provavelmente em outro lugar de onde ele está falhando.

Um monte de coisas pode causar corrupção de pilha.

  • escrevendo após o final (ou início) do bloco de memória que foi alocada.
  • libertar um ponteiro duas vezes, ou libertar um ponteiro que não foi alocado.
  • multithreading seu programa e ligação com o single-threaded (não thread-safe) RTL.
  • alocação de memória de uma pilha e libertá-la em outra pilha.
  • etc., Etc.,

Uma vez que você estiver usando Visual C ++, você pode usar o recurso _CrtSetDbgFlag () da pilha de depuração para ativar a verificação de erros. Você pode configurá-lo para verificar a integridade da pilha em cada chamada para malloc ou livre. Que será executado muito lentamente, mas deve identificar onde o bug é para você.

Pesquise _CrtSetDbgFlag na documentação do compilador.

Eu tenho uma suspeita de que existe uma DLL compilado com uma versão diferente do tempo de execução do C ++ do que o resto da aplicação. Isso muitas vezes resultar em "memória no endereço XXX não poderia ser 'ler' / 'escrita'" violações.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top