创建CFrameWnd引发了第一次异常——为什么?

3
我正在尝试编写一个简单的MFC应用程序,它使用基于CFrameWnd的代码在可滚动窗口中绘制。下面的代码改编自Prosise的《使用MFC编程Windows》第二版89页及以下内容。
当我在调试器中运行此代码时,我会收到两个“一次性异常”。如果我忽略这些异常,窗口将按预期显示,并且我可以在其中绘图。如果我启用“C ++异常”断点,则会得到一个仅包含“内部”代码的堆栈,我没有该源代码。通过逐步执行代码,我发现异常发生在CWnd :: CreateEx中,在调用CreateWindowEx时。
这段代码有什么问题?64位Windows 7,Visual Studio 2013更新4。这是一个调试版本,x64,在静态库中使用MFC,在多字节字符集中使用多线程调试运行时(/ MTd)。
// Viewer.h
#include <afxwin.h>

// Adapted from Prosise "Programming Windows with MFC", 2nd ed, pp 89ff.
class CViewerApp : public CWinApp
{
public:
    virtual BOOL InitInstance();

};

class CMainWindow : public CFrameWnd
{
public:
    CMainWindow();
protected:
    afx_msg void OnPaint();
    afx_msg int OnCreate(LPCREATESTRUCT lpCreateStruct);
    afx_msg void OnSize(UINT nType, int cx, int cy);
    afx_msg void OnHScroll(UINT nCode, UINT nPos, CScrollBar *pScrollBar);
    afx_msg void OnVScroll(UINT nCode, UINT nPos, CScrollBar *pScrollBar);

public:

    DECLARE_MESSAGE_MAP()
};

// Viewer.cpp: Display
#include <afxwin.h>
#include "Viewer.h"

CViewerApp myApp;

BOOL CViewerApp::InitInstance()
{
    m_pMainWnd = new CMainWindow;
    m_pMainWnd->ShowWindow(SW_SHOW);
    m_pMainWnd->UpdateWindow();

    return TRUE;
}
BEGIN_MESSAGE_MAP(CMainWindow, CFrameWnd)
    ON_WM_CREATE()
    ON_WM_SIZE()
    ON_WM_PAINT()
    ON_WM_HSCROLL()
    ON_WM_VSCROLL()
END_MESSAGE_MAP()

CMainWindow::CMainWindow()
{
    Create(NULL, "Viewer", WS_OVERLAPPEDWINDOW | WS_HSCROLL | WS_VSCROLL | WS_MAXIMIZE);
}

int CMainWindow::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
    if(CFrameWnd::OnCreate(lpCreateStruct) == -1)
        return -1;

    return 0;
}

void CMainWindow::OnPaint()
{
}

void CMainWindow::OnSize(UINT nType, int cx, int cy)
{
    //TO DO
}
void CMainWindow::OnHScroll(UINT nCode, UINT nPos, CScrollBar *pScrollBar)
{
}

void CMainWindow::OnVScroll(UINT nCode, UINT nPos, CScrollBar *pScrollBar)
{
}

这很可能是由桌面上运行的应用程序引起的影响,该应用程序安装了全局钩子或使用其他基础结构在您的进程中运行代码。在处理程序内部引发异常,稍后被捕获(否则您将看到第二次机会异常,以及一个未捕获的异常对话框)。要解决此问题,您需要识别故障应用程序,并将其从系统中删除。除此之外,您的代码没有任何问题。阅读Prosise是学习MFC的正确方法。 - IInspectable
哪些异常会被抛出?正如 IInspectable 所说,这可能是由于某种类型的代码注入到您的进程中导致的;如果是这样,您将能够在调用堆栈上看到该 DLL。 - David Ching
输出窗口中的信息为:“在MainWindowTest.exe中0x000007FEFD4B940D处出现了第一次机会异常:Microsoft C++异常:Win32Util::Error,内存位置为0x00000000025EF130。”有两行完全相同的信息。 - Woody20
IInspectable - 有什么建议可以确定故障应用程序吗? Sysinternals autoruns 显示了数百个启动项,而我不确定使用任务管理器终止进程是否会消除错误的根本原因。 - Woody20
这是在第一次机会异常时的堆栈(启用C++异常断点):KernelBase.dll!000007fefd4b940d() 未知 pmls64.dll!000000018007b7e6() 未知 pmls64.dll!00000001800095b5() 未知 pmls64.dll!000000018005af82() 未知 pmls64.dll!000000018005f2c7() 未知 pmls64.dll!000000018005fa11() 未知 pmls64.dll!000000018007db7f() 未知 pmls64.dll!000000018007dc33() 未知 [外部代码] - Woody20
应用程序可以通过在Visual Studio中查看故障线程的调用堆栈来识别。除其他信息外,它还显示包含代码的模块(pmls64.dll)。切换到模块窗口(调试 -> 窗口 -> 模块),并查找该模块,即可显示路径。从那里,就很容易确定该模块属于哪个应用程序。 - IInspectable
1个回答

0

感谢@IInspectable和@David Ching提供的有用建议,我成功找到了问题的原因。这是一个名为“Premier Voice”的软件,最近在没有我的知情下被安装。

我使用Process Explorer来跟踪pmls64.dll的使用情况,并使用任务管理器和autoruns来定位可执行文件。该程序安装在独立的文件夹中的Programs(x86)目录下,并附带卸载功能,我使用了该功能。然后我手动删除了Programs(x86)目录下的文件夹,并删除了一些注册表键。

除此之外,该程序还未经允许在Firefox浏览器上安装了一个插件,我也不得不手动移除。

除了在我的软件中引发异常外,我怀疑Premier Voice就是今天弹出一个窗口问我每个计算机用户的出生日期和性别的原因。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接