to 超级绿豆,这段代码就是我上次写的那个,里面有一个很奇怪的问题,在调试期间按第一个按钮不会出问题,按第二个按钮就会出问题,但是在编译成可执行文件后按第一个按钮会出问题,按第二个按钮就不会出问题,里面有一个API我把参数改了一下,帮忙看看最终原因在哪里,谢谢了。' 以下是模块里的内容   basEx.basOption ExplicitPublic Const EXCEPTION_MAXIMUM_PARAMETERS = 15
Public Type EXCEPTION_RECORD
    ExceptionCode As Long
    ExceptionFlags As Long
    pExceptionRecord As Long    ' Pointer to an EXCEPTION_RECORD structure
    ExceptionAddress As Long
    NumberParameters As Long
    ExceptionInformation(EXCEPTION_MAXIMUM_PARAMETERS) As Long
End TypePublic Type CONTEXT
    FltF0 As Double
    FltF1 As Double
    FltF2 As Double
    FltF3 As Double
    FltF4 As Double
    FltF5 As Double
    FltF6 As Double
    FltF7 As Double
    FltF8 As Double
    FltF9 As Double
    FltF10 As Double
    FltF11 As Double
    FltF12 As Double
    FltF13 As Double
    FltF14 As Double
    FltF15 As Double
    FltF16 As Double
    FltF17 As Double
    FltF18 As Double
    FltF19 As Double
    FltF20 As Double
    FltF21 As Double
    FltF22 As Double
    FltF23 As Double
    FltF24 As Double
    FltF25 As Double
    FltF26 As Double
    FltF27 As Double
    FltF28 As Double
    FltF29 As Double
    FltF30 As Double
    FltF31 As Double
    IntV0 As Double
    IntT0 As Double
    IntT1 As Double
    IntT2 As Double
    IntT3 As Double
    IntT4 As Double
    IntT5 As Double
    IntT6 As Double
    IntT7 As Double
    IntS0 As Double
    IntS1 As Double
    IntS2 As Double
    IntS3 As Double
    IntS4 As Double
    IntS5 As Double
    IntFp As Double
    IntA0 As Double
    IntA1 As Double
    IntA2 As Double
    IntA3 As Double
    IntA4 As Double
    IntA5 As Double
    IntT8 As Double
    IntT9 As Double
    IntT10 As Double
    IntT11 As Double
    IntRa As Double
    IntT12 As Double
    IntAt As Double
    IntGp As Double
    IntSp As Double
    IntZero As Double
    Fpcr As Double
    SoftFpcr As Double
    Fir As Double
    Psr As Long
    ContextFlags As Long
    Fill(4) As Long
End TypePublic Type EXCEPTION_POINTERS
    pExceptionRecord As EXCEPTION_RECORD
    ContextRecord As CONTEXT
End TypePublic Const EXCEPTION_EXECUTE_HANDLER = 1
Public Const EXCEPTION_CONTINUE_EXECUTION = -1
Public Const EXCEPTION_CONTINUE_SEARCH = 0Public Const EXCEPTION_DEBUG_EVENT = 1Public Const EXCEPTION_ACCESS_VIOLATION = &HC0000005Public Declare Function SetUnhandledExceptionFilter Lib "kernel32" ( _
    ByVal lpTopLevelExceptionFilter As Long) As Long'Public Declare Function UnhandledExceptionFilter Lib "kernel32" ( _
    ExceptionInfo As EXCEPTION_POINTERS) As Long' 原来的这个声明我把参数改了,上面那个是原型
Public Declare Function UnhandledExceptionFilter Lib "kernel32" ( _
    ExceptionInfo As Any) As LongPublic hException As LongPrivate Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (Destination As Any, Source As Any, ByVal Length As Long)Public Function MyExceptionProc(ByVal ExceptionInfo As Long) As Long
    On Error Resume Next
    Static s_SigCount As Long
    Dim dwExceptCode As Long
    Dim lResult As Long
    Dim lpExceptionInfo As EXCEPTION_POINTERS
    CopyMemory ByVal lpExceptionInfo, ExceptionInfo, Len(lpExceptionInfo)
    dwExceptCode = lpExceptionInfo.pExceptionRecord.ExceptionCode
    If dwExceptCode = EXCEPTION_ACCESS_VIOLATION Then
        Debug.Print "Access violation caught by MyUnFilter"
        s_SigCount = s_SigCount + 1
        If s_SigCount < 5 Then
            lResult = EXCEPTION_CONTINUE_EXECUTION
        Else
            lResult = EXCEPTION_EXECUTE_HANDLER
        End If
    Else
        lResult = EXCEPTION_CONTINUE_SEARCH
    End If
    MyExceptionProc = lResult
End Function' 以下是窗体里的内容 frmMain.frmOption ExplicitPrivate Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" ( _
    Destination As Any, Source As Any, ByVal Length As Long)Dim lpExceptionInfo As EXCEPTION_POINTERSPrivate Sub Command1_Click()
    On Error GoTo errFinish
    UnhandledExceptionFilter hException
    Exit Sub
errFinish:
    MsgBox Err.Description
End SubPrivate Sub Command2_Click()
    On Error GoTo errFinish
    CopyMemory ByVal 1, ByVal 2, 3
    Exit Sub
errFinish:
    MsgBox Err.Description
End SubPrivate Sub Form_Load()
    hException = SetUnhandledExceptionFilter(AddressOf MyExceptionProc)
End Sub

解决方案 »

  1.   

    那偶就upup吧,就等綠豆又來講子類吧
      

  2.   

    呵呵,搞得我好像是子类处理狂一样的。
    首先,
    UnhandledExceptionFilter的参数类型是EXCEPTION_POINTERS,也就是异常的信息结构,而不是函数地址。
    SetUnhandledExceptionFilter返回的是前一次用SetUnhandledExceptionFilter设定的异常处理函数的地址。
    所以,你在UnhandledExceptionFilter参数里使用SetUnhandledExceptionFilter返回的函数地址肯定是错了。
    其次,
    EXCEPTION_EXECUTE_HANDLER的意思是,告诉系统从UnhandledExceptionFilter函数返回,然后执行相应的异常处理程序,再然后基本上就是程序结束了。
    EXCEPTION_CONTINUE_EXECUTION意思是,同样从UnhandledExceptionFilter函数返回,然后重新从发生异常的地方开始执行。或者可以通过修改作为参数传入的lpEXCEPTION_POINTERS结构的内容来修改重新开始地址。
    EXCEPTION_CONTINUE_SEARCH意思是,继续执行UnhandledExceptionFilter,也就是遵照函数SetErrorMode设定的标志(例如,不显示系统默认的应用程序出错提示框等),或者调用应用程序错误提示框。再说说你的异常处理函数,你出错首先是因为你没有捕捉到内存存取异常(&HC00005)这个错误,你之所以没有捕捉到这个错误是因为你的EXCEPTION_POINTERS结构写错了。记得我说过VB自带的Win32 API文件有很多翻译错误的地方,在这里就是一个很典型的例子。
    MSDN里EXCEPTION_POINTERS的声明是这样的:
    typedef struct _EXCEPTION_POINTERS {
      PEXCEPTION_RECORD ExceptionRecord; 
      PCONTEXT ContextRecord; 
    } EXCEPTION_POINTERS, *PEXCEPTION_POINTERS; 
    也就是说它里面的ExceptionRecord和ContextRecord应该分别是*EXCEPTION_RECORD和*CONTEXT类型,说白了就是两个结构的地址指针,而不是像API文件中写那样是两个结构。
    所以,在VB里应该声明为
    Public Type EXCEPTION_POINTERS
        pExceptionRecord As Long
        ContextRecord As Long
    End Type
    而不是
    Public Type EXCEPTION_POINTERS
        pExceptionRecord As EXCEPTION_RECORD
        ContextRecord As CONTEXT
    End Type
    ,所以我写的那段异常处理里面用copymemory获得pExceptionRecord结构的内容。
    错误既然捕捉不到,那自然就执行到lResult = EXCEPTION_CONTINUE_SEARCH这一句了,这句啥意思呢?看看上面就知道了,所以你就觉得自己莫名其妙错了。
    还有啥问题吗?