News: LimeReport new version 1.5 has been released
Вышла новая версия LimeReport 1.5

Recent Posts

Pages: [1] 2 3 ... 10
1
Discussion | Обсуждение / Re: Linux vs Windows
« Last post by Tux on April 21, 2026, 04:00:18 pm »
LimeReport похоже имеет критический лаг при инициализации на Linux (из-за CUPS) и на Windows (из-за сетевых принтеров).
В Linux лечится через
 qputenv("CUPS_SERVER", "localhost:1");
в самом начале main.
Это сокращает время загрузки тестового отчёта с 5000мс до 3мс без изменения настроек системы.

P.S. Хотя лучше было бы поправить сами исходники LimeReport, но, увы, Linux на рабочих и домашних машинах не так часто встречается.
2
1. Окружение

ОС: Debian 13 (Trixie), amd64
Qt: 6.10.1 (x86_64, shared, GCC 14.2.0)
LimeReport: последняя версия из репозитория, собрана с опцией -DQT_VERSION_MAJOR=6 -DLIMEREPORT_DEMO=ON
Компилятор: GCC 14.2.0
Система сборки: CMake + Ninja

2. Описание проблемы

При одновременном использовании в одном процессе QQmlEngine (с загруженным QML-компонентом) и LimeReport ReportEngine происходит повреждение кучи (heap corruption). Программа завершается с сообщением:

Quote
corrupted size vs. prev_size while consolidating

Краш происходит в деструкторах при завершении программы — в момент уничтожения синглтона
LimeReport::ScriptEngineManager, который владеет собственным QJSEngine (и, соответственно, QV4::ExecutionEngine).

3. Шаги для воспроизведения
3.1. Скрипт сборки LimeReport

Code: [Select]
#! /bin/bash
cmake -G "Ninja" \
    -B build \
    -S src \
    -DQT_VERSION_MAJOR=6 \
    -DLIMEREPORT_DEMO=ON \
    -DCMAKE_INSTALL_PREFIX=install \
    -DCMAKE_TOOLCHAIN_FILE=/root/toolchain.cmake

cmake --build build --config Release --parallel --target install

3.2. CMakeLists.txt тестового проекта

Code: [Select]
cmake_minimum_required(VERSION 3.14)
project(limereport-tests)

enable_testing()
find_package(Qt6 REQUIRED COMPONENTS Core Test Widgets PrintSupport Qml)
find_library(limereport NAMES limereport limereport-qt6)
find_path(LIME_REPORT_INCLUDE_DIRS
    NAMES "LimeReport/LimeReport" "limereport/LimeReport"
    PATH_SUFFIXES "include" HINTS ENV CMAKE_PREFIX_PATH)

set(CMAKE_INCLUDE_CURRENT_DIR ON)
set(CMAKE_AUTOMOC ON)

qt_add_executable(tst_limereport_heap tst_limereport_heap.cpp)
add_test(NAME tst_limereport_heap COMMAND tst_limereport_heap)

target_link_libraries(tst_limereport_heap PRIVATE
    Qt6::Test Qt6::Core Qt6::Widgets Qt6::PrintSupport Qt6::Qml
    ${limereport}
)
target_include_directories(tst_limereport_heap PRIVATE ${LIME_REPORT_INCLUDE_DIRS})

# Файл отчёта содержит один элемент — ReportHeader
qt_add_resources(tst_limereport_heap "resources"
    PREFIX "/" FILES ReportWithHeadBand.lrxml)

set_target_properties(tst_limereport_heap PROPERTIES
    CXX_STANDARD 23 CXX_STANDARD_REQUIRED ON)


3.3. Тестовый файл tst_limereport_heap.cpp

Code: [Select]
#include <QObject>
#include <QtTest>
#include <QGraphicsScene>
#include <QQmlApplicationEngine>
#include <QQmlComponent>
#include <QVariant>
#include "limereport/LimeReport"

using namespace LimeReport;

// Файл отчёта .lrxml встроен в ресурсы приложения.
// Отчёт содержит единственный элемент — ReportHeader.
static const char ResourceFileName[] = ":/ReportWithHeadBand.lrxml";

class TestLimereportHeap: public QObject
{
    Q_OBJECT

private slots:

    // Контрольный тест: только QQmlEngine без загрузки компонента.
    // Ошибка НЕ воспроизводится — одного создания движка недостаточно.
    void testQV4Init()
    {
        auto qmlEngine = std::make_unique<QQmlEngine>();

        std::unique_ptr<ReportEngine> report = std::make_unique<ReportEngine>();
        report->loadFromFile(ResourceFileName);
        std::shared_ptr<QGraphicsScene> scene(report->createPreviewScene());
        // Деструкторы вызываются в порядке: scene, report, qmlEngine
    }

    // Минимальный тест, воспроизводящий ошибку.
    // Ключевое отличие от testQV4Init: загружается QML-компонент.
    // Это инициализирует QV4::ExecutableCompilationUnit и связанные
    // глобальные структуры QV4, что приводит к конфликту с внутренним
    // QJSEngine библиотеки LimeReport при завершении программы.
    void testQV4Compile()
    {
        auto qmlEngine = std::make_unique<QQmlEngine>();

        // Загрузка минимального QML-компонента из строки.
        // Именно этот шаг является триггером ошибки.
        QQmlComponent component(qmlEngine.get());
        component.setData("import QtQuick\nItem {}", QUrl());
        qDebug() << component.status() << component.errorString();

        // ReportEngine создаёт ScriptEngineManager (синглтон),
        // который внутри владеет собственным QJSEngine.
        std::unique_ptr<ReportEngine> report = std::make_unique<ReportEngine>();
        qDebug() << report->loadFromFile(ResourceFileName);
        std::shared_ptr<QGraphicsScene> scene(report->createPreviewScene());

        // При выходе из функции уничтожаются scene, report и qmlEngine.
        // Синглтон ScriptEngineManager уничтожается позже — через atexit,
        // после того как QV4-инфраструктура qmlEngine уже освобождена.
        // Это вызывает heap corruption.
    }
};

QTEST_MAIN(TestLimereportHeap)
#include "tst_limereport_heap.moc"

4. Фактический результат

Тест testQV4Compile проходит (все assertions успешны), однако после завершения тестового фреймворка процесс падает с сообщением в stderr:

Quote
********* Start testing of TestLimereportHeap *********
Config: Using QtTest library 6.10.1, Qt 6.10.1 (x86_64-little_endian-lp64
        shared (dynamic) release build; by GCC 14.2.0), debian 13
PASS   : TestLimereportHeap::initTestCase()
QDEBUG : TestLimereportHeap::testQV4Compile() true ""
PASS   : TestLimereportHeap::testQV4Compile()
PASS   : TestLimereportHeap::cleanupTestCase()
Totals: 3 passed, 0 failed, 0 skipped, 0 blacklisted, 260ms
********* Finished testing of TestLimereportHeap *********
corrupted size vs. prev_size while consolidating

Стек вызовов на момент краша:

Quote
libc!malloc_printerr
libc!_int_free_merge_chunk
libc!__GI___libc_free
libQt6Qml!QV4::ExecutableCompilationUnit::~ExecutableCompilationUnit
libQt6Qml!QV4::ExecutionEngine::~ExecutionEngine
libQt6Qml!QJSEngine::~QJSEngine
liblimereport-qt6!LimeReport::ScriptEngineManager::~ScriptEngineManager
liblimereport-qt6!LimeReport::Singleton<ScriptEngineManager>::destroy
libc!__run_exit_handlers   <-- вызов через atexit

5. Ожидаемый результат

Процесс завершается без ошибок. LimeReport корректно сосуществует с QQmlEngine в одном процессе.

6. Анализ причины

Проблема воспроизводится при выполнении всех трёх условий одновременно:
  • В процессе создаётся и уничтожается QQmlEngine с загруженным QML-компонентом (QQmlComponent::setData / load). Простое создание QQmlEngine или QJSEngine без загрузки компонента ошибки не вызывает.
  • Создаётся LimeReport::ReportEngine, который лениво инициализирует синглтон ScriptEngineManager, содержащий собственный QJSEngine.
  • Синглтон ScriptEngineManager регистрируется через механизм atexit и уничтожается после выхода из main — то есть позже, чем QQmlEngine, управляемый умным указателем внутри теста.
При загрузке QML-компонента Qt компилирует его в байткод и создаёт QV4::ExecutableCompilationUnit, который регистрирует данные в глобальном состоянии QV4 (таблицы типов, строковые пулы и т.д.). При уничтожении QQmlEngine это глобальное состояние частично освобождается. Впоследствии, когда atexit вызывает деструктор синглтона ScriptEngineManager, его внутренний QJSEngine обращается к уже освобождённым структурам QV4, что вызывает повреждение кучи.
3
Discussion | Обсуждение / Re: Повторная печать отчета
« Last post by Arin Alex on February 16, 2026, 11:57:27 pm »
Да, так и задумывалось :) Если принтер не был передан в параметрах, то он запрашивается у пользователя. Если вам надо запрашивать его каждый раз, это можно делать в коде на вашей стороне и передавать этот принтер в параметрах вызова печати.
4
Discussion | Обсуждение / Повторная печать отчета
« Last post by Tux on February 12, 2026, 02:45:32 pm »
Доброго времени суток!
Допустим, я подготовил отчёт и пытаюсь его распечатать с помощью функции printReport
При первой печати всё нормально - будет окошко, в котором я смогу выбрать диапазон печати и прочее.
Но, при повторном вызове функции printReport печать произойдёт без какой либо возможности выбора.
Это так задумано?
5
Приветствую, так не получится.
Возможности программно управлять отчетом из кода c++ сильно ограничены
По факту, генерация отчета управляется скриптами, которые живут в самом отчете.
   
6
Приветствую, добавил несколько дополнительных свойств к BarcodeItem: borderType, borderWidth на комбинации barcodeType: BARCODE_BOX & borderWidth: 0 рамка должна пропасть :) 
Можно забрать проверить
7
Спасибо, но теперь другая проблема, мне нужно печатать код без рамки, никакие настройки рамку вокруг ITF 14 не убирают
8
Я разместил в отчёте изображение, присвоил ему objectName. Изображение генерируется программно. Как можно программно извлечь размеры элемента отчёта (ItemGeometry), чтобы произвести рендер в нужной пропорции? Как извлечь handle самого элемента?

Code: [Select]
LimeReport::ReportEngine report;
qDebug() << report.loadFromFile("report-pic.lrxml");
auto pic = report.findChild<QObject*>("Picture");  // возвращает nullptr
9
Discussion | Обсуждение / Re: Linux vs Windows
« Last post by Tux on December 28, 2025, 07:25:48 pm »
4.8 МиБ
10
Discussion | Обсуждение / Re: Linux vs Windows
« Last post by Subst on December 28, 2025, 06:51:37 pm »
так... увидеть отчет нельзя
размер файла шаблона секретом не является?
Pages: [1] 2 3 ... 10