Description
Hi,
The sample below creates 10 PDF files with the size A4 named "Test0.pdf".."Test9.pdf".
Each document contains 3 pages and each page contains a one large png image.
"MyFillpage1.png" on page 1
"MyFillpage2.png" on page 2
"MyFillpage3.png" on page 3
Each png is 1130x1600px in size and has alpha channel (32Bit)
When I execute the program I notice a memory leak of roughly 28MB on Ubuntu between the first and second iteration of creating a PDF.
The other iterations seem to be stable and no additional leaking memory.
Why there is such a large drop of free memory resp. increase of used memory after the first iteration ?
HPDF_Free is called at the end of each iteration.
Any suggestion or advise what goes wrong is aprechiated.
Procedure for memory determination:
At the begin of the program and after each iteration the sample requires to enter a value followed by ENTER. This gives time to note the used memory
before the PDF creation and after each iteration of PDF creation.
I determined the used memory with the command: "top -p "
Attached files to this issue:
- MyFullpage1.png
- MyFullpage2.png
- MyFullpage3.png
- sample output Test0.pdf (one of 10 identical PDF's)
Environment:
Files/Folders:
<path_to_current_folder>/sample.cpp
<path_to_current_folder>/include/
<path_to_current_folder>/lib/libhpdf.a
installed libraries:
sudo apt install libhpdf-dev libpng-dev
sudo apt install zlib1g-dev
compile/link:
g++ -std=c++17 -m32 -o my_program sample.cpp -Iinclude <path_to_current_folder>/lib/libhpdf.a -lpng -lz
Sample code:
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sstream>
#include <iostream>
#include <filesystem>
#include "hpdf.h"
std::string libHaruError;
void error_handler(HPDF_STATUS error_no,
HPDF_STATUS detail_no,
void *user_data)
{
std::stringstream ss;
ss << std::hex << "PDF engine error : error no. = 0x" << static_cast<unsigned int>(error_no) <<
std::dec << ", detail no.= " << static_cast<unsigned int>(detail_no) <<
" !";
libHaruError = ss.str();
}
int main (int argc, char **argv)
{
(void) argc; /* Not used */
(void) argv; /* Not used */
std::cout << "Started...press a value and ENTER after memory noted" << std::endl;
int wait;
std::cin >> wait;
for (int i=0; i<10; ++i)
{
// Create PDF
HPDF_Doc pdf = HPDF_New(error_handler, NULL);
if ( HPDF_SetCompressionMode (pdf, HPDF_COMP_ALL) != HPDF_OK )
{
std::cout << libHaruError.c_str()<< std::endl;
}
// Page size
HPDF_REAL width = 2.83f * 210; //A4
HPDF_REAL height = 2.83f * 297; //A4
// Add page 1
HPDF_Page page = HPDF_AddPage(pdf);
if ( HPDF_Page_SetWidth (page, width) != HPDF_OK ||
HPDF_Page_SetHeight(page, height) != HPDF_OK )
{
std::cout << libHaruError.c_str()<< std::endl;
}
HPDF_Image image = HPDF_LoadPngImageFromFile(pdf, "MyFullpage1.png");
HPDF_UINT imageWidth = HPDF_Image_GetWidth(image);
HPDF_UINT imageHeight= HPDF_Image_GetHeight(image);
if (HPDF_Page_DrawImage(page, image, 0, 0, width, height) != HPDF_OK)
{
std::cout << libHaruError.c_str()<< std::endl;
}
// Add page 2
HPDF_Page page2 = HPDF_AddPage(pdf);
if ( HPDF_Page_SetWidth (page2, width) != HPDF_OK ||
HPDF_Page_SetHeight(page2, height) != HPDF_OK )
{
std::cout << libHaruError.c_str()<< std::endl;
}
HPDF_Image image2 = HPDF_LoadPngImageFromFile(pdf, "MyFullpage2.png");
imageWidth = HPDF_Image_GetWidth(image2);
imageHeight= HPDF_Image_GetHeight(image2);
if (HPDF_Page_DrawImage(page2, image2, 0, 0, width, height) != HPDF_OK)
{
std::cout << libHaruError.c_str()<< std::endl;
}
// Add page 3
HPDF_Page page3 = HPDF_AddPage(pdf);
if ( HPDF_Page_SetWidth (page3, width) != HPDF_OK ||
HPDF_Page_SetHeight(page3, height) != HPDF_OK )
{
std::cout << libHaruError.c_str()<< std::endl;
}
HPDF_Image image3 = HPDF_LoadPngImageFromFile(pdf, "MyFullpage3.png");
imageWidth = HPDF_Image_GetWidth(image3);
imageHeight= HPDF_Image_GetHeight(image3);
if (HPDF_Page_DrawImage(page3, image3, 0, 0, width, height) != HPDF_OK)
{
std::cout << libHaruError.c_str()<< std::endl;
}
std::stringstream ss;
ss << "/tmp/Test" << i << ".pdf";
// Remove file if exist already
std::filesystem::remove(ss.str());
// Save PDF
if (HPDF_SaveToFile(pdf, ss.str().c_str()) != HPDF_OK)
{
std::cout << libHaruError.c_str()<< std::endl;
}
std::cout << "PDF <" << ss.str() << "> stored. Press value and ENTER after memory noted" << std::endl;
HPDF_Free(pdf);
// wait for keyboard input to measure memory with "top" command for the current pid
int wait;
std::cin >> wait;
}
std::cout << "Done" << std::endl;
return 0;
}