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

使用Poppler-Qt6时出现运行时访问违例问题求助

在Visual Studio中使用poppler-qt6+Qt6触发运行时访问违例的排查方案

问题背景

在Visual Studio中构建基于poppler-qt6和Qt6的极简C++应用时,出现诡异的运行时访问违例:参照poppler-qt6示例编写的代码可正常运行,但只要在main函数末尾添加return app.exec()或创建QLabel对象,就会在Poppler::Document::load()行触发访问违例。单独使用Qt6组件的代码无异常,怀疑是兼容性问题但缺乏排查方向。

可正常运行的代码

#include <poppler/qt6/poppler-qt6.h>
#include <Qt6/QtWidgets/QApplication>
#include <Qt6/QtWidgets/QLabel>

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);

    const wchar_t* wCharFilepath = L"C:\\poppler-test\\test.pdf";
    QString qFilepath = QString::fromWCharArray(wCharFilepath);
        
    std::unique_ptr<Poppler::Document> documentPtr = Poppler::Document::load(qFilepath);
    if (!documentPtr) {
        std::cout << "Failed to load document\n";
        exit(1);
    }
    else {
        std::cout << "loaded pdf\n";
    }

    std::unique_ptr<Poppler::Page> pagePtr = documentPtr->page(0);
    
    if (!pagePtr) {
        std::cout << "Failed to get page\n";
    }
    else {
        std::cout << "got pagePtr\n";
    }
}

触发异常的场景

  • 在上述main函数末尾添加return app.exec()
  • 在上述main函数中添加QLabel* l = new QLabel();

单独Qt6代码可正常运行

int main(int argc, char* argv[])
{
    QApplication app(argc, argv);
    QLabel* l = new QLabel();
    return app.exec();
}

排查与解决步骤

1. 验证环境版本一致性

确保poppler-qt6与Qt6的编译环境完全匹配:

  • Qt6版本一致(比如都是6.5.3)
  • 编译器版本一致(比如都是VS2022的MSVC 17.7)
  • 平台位数统一(x86或x64)
  • 调试/发布模式对应(Debug版poppler配Debug Qt,Release版同理)

2. 检查运行时库链接设置

在Visual Studio项目属性中,确认Qt6和poppler-qt6的运行时库选项统一:

  • 要么均为/MD(多线程DLL)
  • 要么均为/MT(多线程静态)
    混合使用会导致堆内存管理冲突,触发访问违例。

3. 调试定位崩溃细节

启用Visual Studio原生调试:

  • 在Poppler::Document::load()处设置断点,进入函数内部查看具体崩溃位置
  • 查看调用栈,确认崩溃时的函数调用链,判断是poppler内部内存错误还是Qt UI初始化导致的冲突

4. 调整代码执行顺序

尝试将poppler的PDF加载逻辑放到Qt UI初始化之后:

  • 先创建UI组件或启动事件循环前执行加载
  • 或用QTimer::singleShot延迟加载,避免与Qt的初始化逻辑冲突(示例代码如下)
int main(int argc, char* argv[])
{
    QApplication app(argc, argv);
    QLabel* l = new QLabel();

    // 延迟执行PDF加载,避开Qt初始化阶段
    QTimer::singleShot(0, [&](){
        const wchar_t* wCharFilepath = L"C:\\poppler-test\\test.pdf";
        QString qFilepath = QString::fromWCharArray(wCharFilepath);
        
        std::unique_ptr<Poppler::Document> documentPtr = Poppler::Document::load(qFilepath);
        if (!documentPtr) {
            std::cout << "Failed to load document\n";
            exit(1);
        }
        else {
            std::cout << "loaded pdf\n";
        }

        std::unique_ptr<Poppler::Page> pagePtr = documentPtr->page(0);
        
        if (!pagePtr) {
            std::cout << "Failed to get page\n";
        }
        else {
            std::cout << "got pagePtr\n";
        }
    });

    return app.exec();
}

5. 自行编译poppler-qt6

若使用第三方预编译包,尝试从poppler源码自行编译:

  • 下载对应版本的poppler源码
  • 用与项目一致的Qt6和MSVC版本编译,确保编译选项完全匹配
  • 替换项目中的预编译库为自行编译的版本测试

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.27 20:42:16