You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

VS2022 x64 MFC程序打开CDatabase连接ACCDB退出时抛出异常

问题根因

该崩溃属于64位Microsoft 365附带的Access ACCDB ODBC驱动的已知缺陷,和代码中显式调用db.Close()的逻辑无关。
Access ODBC驱动加载时,会自动向C运行时(CRT)的进程退出回调表注册自身的清理逻辑。但MFC程序在AfxWinMain执行返回后,MFC框架、ODBC核心环境的销毁顺序,和Office驱动注册的清理回调执行顺序不匹配:驱动清理逻辑执行时,它依赖的运行时上下文已经被提前释放,最终在Mso20win32client.dll中触发访问违例。
代码中调用的db.Close()仅会释放当前数据库连接资源,不会触发ODBC驱动卸载,也不会移除驱动注册的进程退出回调,因此即使提前关闭连接,退出阶段仍会触发该异常。

对照验证

可以通过几个简单测试确认根因:

  • 将编译目标切换为x86,使用32位Access驱动运行,崩溃不会出现
  • 更换连接串为旧版.mdb格式Access驱动,连接mdb格式数据库运行,崩溃不会出现
  • 更换ODBC数据源为SQL Server等非Access数据源运行,崩溃不会出现
解决方案

按推荐优先级排序:

  • 优先方案:改用ACE OLEDB提供程序访问ACCDB,绕开存在缺陷的ODBC驱动
    将OpenEx的连接串替换为OLEDB格式即可,注意使用的ACE驱动架构要和程序编译目标匹配(64位程序用64位ACE,32位程序用32位ACE),示例代码:
    CDatabase db;
    if (db.OpenEx(_T("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=D:\\Test.ACCDB;Jet OLEDB:Database Password="), CDatabase::noOdbcDialog))
    {
        AfxMessageBox(_T("DB Opened"));
        db.Close();
    }
    
  • 必须使用ODBC驱动时:手动提前释放ODBC环境,避开CRT退出阶段的顺序冲突
    重载CWinApp派生类的ExitInstance方法,在调用基类方法前主动释放ODBC全局资源,强制驱动提前完成清理,示例代码:
    int CYourAppClass::ExitInstance()
    {
        // 主动释放ODBC环境句柄,终止ODBC组件
        AFX_SQL_SYNC(::SQLFreeHandle(SQL_HANDLE_ENV, SQL_NULL_HANDLE));
        AfxOdbcTerm();
        return CWinApp::ExitInstance();
    }
    
  • 临时规避:忽略该退出阶段异常
    该崩溃发生在进程退出的最后阶段,所有业务逻辑、用户资源均已完成释放,不会造成数据损坏。若暂时无法调整驱动调用逻辑,可在VS调试配置中添加对应异常的忽略规则;Release模式下系统会直接回收进程地址空间,终端用户不会感知到该异常。

内容的提问来源于stack exchange,提问作者Andrew Truckle

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.01 19:06:40