无法保留指向内存的指针

时间:2016-06-22 06:24:06

标签: c++ c++11 pdfium

这就是我使用Google的PDFium库加载pdf的方法。我收到了void*

doc = FPDF_LoadDocument("media1.pdf", NULL);

现在我想将此文档保存在FPDF_DOCUMENT的向量中,该向量基本上是void*我从上面的代码中收到的。这就是我在向量中保存它的方式:

pdfs.push_back(doc);

问题是,当我超出此方法的范围时,我无法访问doc指向的内存。我想当doc超出范围时,GC会释放内存。我了解了这个Valgrid调试工具。 doc是在与加载pdf的命令相同的函数中声明的。

我基本上想要保留加载的pdf,以便以后可以访问它并从中呈现页面。

Valgrind输出:

==4816== 64 bytes in 1 blocks are definitely lost in loss record 175 of 616
==4816==    at 0x4C2A105: operator new(unsigned long) (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so)
==4816==    by 0x85175B: FPDFBitmap_Create (in /home/ec2-user/Vid/dist/Debug/GNU-MacOSX/video_creator_mount)
==4816==    by 0x4586A1: Blrt::PDFManager::RenderPDFPage(int, int) (PDFManager.cc:159)

以下是PDFManager中的方法:

std::unique_ptr<Canvas::LoadedPDFInfo> PDFManager::LoadPDF(const std::vector<uint8_t>& data, size_t dataSize)
{
    if(!initPDFIUM) {
        InitPDFIUM();
        currentPDFHandle = 0;
    }

    FPDF_DOCUMENT doc;
   // doc = FPDF_LoadMemDocument(&data[0], dataSize, nullptr);
   doc = FPDF_LoadDocument("media1.pdf", NULL);
    if (!doc) {
      unsigned long err = FPDF_GetLastError();
      fprintf(stderr, "Load pdf docs unsuccessful: ");
      switch (err) {
        case FPDF_ERR_SUCCESS:
          fprintf(stderr, "Success");
          break;
        case FPDF_ERR_UNKNOWN:
          fprintf(stderr, "Unknown error");
          break;
        case FPDF_ERR_FILE:
          fprintf(stderr, "File not found or could not be opened");
          break;
        case FPDF_ERR_FORMAT:
          fprintf(stderr, "File not in PDF format or corrupted");
          break;
        case FPDF_ERR_PASSWORD:
          fprintf(stderr, "Password required or incorrect password");
          break;
        case FPDF_ERR_SECURITY:
          fprintf(stderr, "Unsupported security scheme");
          break;
        case FPDF_ERR_PAGE:
          fprintf(stderr, "Page not found or content error");
          break;
        default:
          fprintf(stderr, "Unknown error %ld", err);
      }
         fprintf(stderr, ".\n");

      return nullptr;
    }
    pdfs.push_back(doc);
    //doc = nullptr;
    std::unique_ptr<Canvas::LoadedPDFInfo> pdfInfo(new Canvas::LoadedPDFInfo);
    pdfInfo->handle = ++currentPDFHandle;
    pdfInfo->totalPageNum = FPDF_GetPageCount(doc);
        std::cout << "ERROR\n";
    return pdfInfo;
}

pdfs是在PDFManager.h中声明的向量:

namespace Blrt
{
    class PDFManager
    {
        public:
            static std::unique_ptr<Canvas::LoadedPDFInfo> LoadPDF(const std::vector<uint8_t>& data, size_t dataSize);
            static std::unique_ptr<Canvas::TextureData> RenderPDFPage(int32_t pdfHandle, int32_t pageNum);
            static void Dispose();

        private:
            static void InitPDFIUM();
            static void UnsupportedHandler(UNSUPPORT_INFO*, int type);
            static bool initPDFIUM;
            static int32_t currentPDFHandle;
            static std::vector<FPDF_DOCUMENT> pdfs;
            static int32_t nextMultipleOf4(size_t num);
    };
}

以下是我访问pdf以访问使用上述方法加载的pdf数据的方法的一部分:

std::unique_ptr<Canvas::TextureData> PDFManager::RenderPDFPage(int32_t pdfHandle, int32_t pageNum)
{

    if (pdfs[pdfHandle-1]) {
        auto pdf = *(pdfs[pdfHandle-1]);
        std::cout << pdfHandle << "    " << pageNum << "    " <<pdfs.size() << "\n";
        if (1 <= pageNum && pageNum <= FPDF_GetPageCount(pdf)) {

            auto page = FPDF_LoadPage(pdf, pageNum);

            if(page) {
                auto textPage = FPDFText_LoadPage(page);
                if (textPage) {
                    auto scale = 2.0;
                    auto maxTexSize = VideoCreator::VideoCreator::MaxTextureSize;
                    auto orgWidth = FPDF_GetPageWidth(page);
                    auto orgHeight = FPDF_GetPageHeight(page);
                    auto targetWidth = orgWidth * scale;
                    auto targetHeight = orgHeight * scale;
                    if (targetWidth > targetHeight) {
                        if (targetWidth > maxTexSize) {
                            scale = maxTexSize / targetWidth;
                        }
                    } else {
                        if (targetHeight > maxTexSize) {
                            scale = maxTexSize / targetHeight;
                        }
                    }

1 个答案:

答案 0 :(得分:0)

从valgrind消息中,它不是您正在泄漏的文档,而是您稍后创建的位图。由于c ++中没有gc,因此未清除doc。您必须自己关闭文档。

但是,要修复错误,您需要清理在PDFManager.cc:159中创建的位图。