Excepções lançada (erros encontrados) após o término do Programa
Pergunta
Eu tenho um aplicativo que parece lançar exceções apenas após o programa ter sido fechado. E é muito inconsistente. (Todos nós sabemos como erros divertido inconsistentes são ...)
Meu palpite é que há um erro durante o processo de limpeza. Mas estes memória de leitura / gravação erros parecem indicar algo de errado no meu uso de código "inseguro" (ponteiros?).
O que eu estou em interessado é o que é o melhor método para depurar estas situações?
Como você depurar um programa que já fechou
Estou à procura de um ponto de partida para quebrar um problema maior.
Esses erros parecem apresentar-se de diversas formas (algumas tempo de execução, alguns depuração):
1: .NET-BroadcastEventWindow.2.0.0.0.378734a.0: Application.exe - Application Error
The instruction at "0x03b4eddb" referenced memory at "0x00000004". The memory could not be "written". 2: Application.vshost.exe - Application Error
The instruction at "0x0450eddb" referenced memory at "0x00000004". The memory could not be "written". 3: Application.vshost.exe - Application Error
The instruction at "0x7c911669" referenced memory at "0x00000000". The memory could not be "read". 4: Application.vshost.exe - Application Error
The instruction at "0x7c910ed4" referenced memory at "0xfffffff8". The memory could not be "read".
Solução
Se seu aplicativo é multi-threaded você poderia estar recebendo erros de threads de trabalho que não são devidamente terminais e tentando acessar objetos descartados.
Outras dicas
Eu tive esse problema usando o componente AcrobarReader COM. Cada agora e, em seguida, após a saída do aplicativo eu tinha "Application.vshost.exe - Erro de aplicativo" "memória não pôde ser lida". GC.Collect () e WaitForPendingFinalizers () não ajuda.
Meu google-fu me levam a esta página: http://support.microsoft.com/kb / 826220 . Eu modifiquei o método 3 para o meu caso.
processo Usando o explorador eu achei que AcroPDF.dll não é liberado antes da última linha na função principal. Então, aqui vêm as chamadas de API.
DLLImports (DLLImport está em System.Runtime.InteropServices namespace):
<DllImport("kernel32.dll", EntryPoint:="GetModuleHandle", _
SetLastError:=True, CharSet:=CharSet.Auto, _
CallingConvention:=CallingConvention.StdCall)> _
Public Overloads Shared Function GetModuleHandle(ByVal sLibName As String) As IntPtr
End Function
<DllImport("kernel32.dll", EntryPoint:="FreeLibrary", _
SetLastError:=True, CallingConvention:=CallingConvention.StdCall)> _
Public Overloads Shared Function FreeLibrary(ByVal hMod As IntPtr) As Integer
End Function
E, em seguida, antes da saída do aplicativo:
Dim hOwcHandle As IntPtr = GetModuleHandle("AcroPDF.dll")
If Not hOwcHandle.Equals(IntPtr.Zero) Then
FreeLibrary(hOwcHandle)
Debug.WriteLine("AcroPDF.dll freed")
End If
Este procedimento pode ser modificado por qualquer outra dll mal-comportados. Só espero que não introduz novos bugs.
Eu vi plently de erros como esta recentemente. Meus problemas foram releated à forma como o CRT (C Runtime) intereacting com o .NET runtime limpa um processo de fechamento. Meu aplicativo é complicada pelo fato de que é C ++, mas permite que suplementos para a cheia, alguns que são escritos em C #.
Para depurar isso, eu acho que você vai precisar usar depuração nativa. Visual Studio (conjunto de depuração de modo misto) ou WinDbg. Olhe para cima como usar o servidor de símbolos públicos da Microsoft para baixar PDBs para os componentes do Windows -. Você vai necessidade esses símbolos
Muitos dos nossos problemas foram com suporte ao cliente (terrível) COM do .NET. Eu digo terrível, uma vez que não faz referência a contar corretamente (sem um monte de trabalho no final do colaborador). objectos COM não estavam a ser referenciado-contadas para baixo a zero até lixo recolha foi feito. Isso muitas vezes configuração estranha problemas de tempo durante o desligamento -. Com objetos sendo limpo por muito tempo depois que eles deveriam ter sido
A palavra extravagante para "inconsistente" é "não-determinista." E o que acontece não-determinística no ambiente .NET? Objeto destruição.
Quando isso aconteceu comigo, o culpado foi na classe que eu escrevi para embrulhar as chamadas inseguras para uma API externa. Eu coloquei o código de limpeza em destrutor da classe, esperando o código a ser chamado quando o objeto saiu do escopo. Mas isso não é como a destruição de objeto funciona em .NET, Quando um objeto sai do escopo, ele é colocado na fila do finalizador, e seu destruidor não obter chamado até o finalizador fica em torno a ele. Não pode fazer isso até depois das termina programa. Se isso acontecer, o resultado será muito parecido com o que você está descrevendo aqui.
Uma vez eu fiz a minha classe implementar IDisposable
, e explicitamente chamado Dispose()
sobre o objeto quando eu terminei com ele, o problema foi embora. (Outra vantagem de implementar IDisposable é que você pode instanciar o objeto no início de um bloco using
e estar confiante de que Dispose () terá quando as folhas do código do bloco.)
tentar isso para forçar o erro acontecer enquanto estiver sob o controle do programa
//set as many statics as you can to null;
GC.Collect();
GC.WaitForPendingFinalizers();
} //exit main
O erro parou de aparecer depois de usar o código sugerido:
GC.Collect();
GC.WaitForPendingFinalizers();