Public bug reported: QV4::EvalInstructionSelection::compile(bool generateUnitData) in src/qml/compiler/qv4isel_p.cpp, line 369-370: if ((unit->data == nullptr) && (do_save || generateUnitData)) unit->data = jsGenerator->generateUnit(); Above this line, I see that do_save is always true. So, unit->data is always generated, regardless of the value of generateUnitData.
However, by tracing to callers of this function, it's revealed that callers expect unit->data to be NULL if generateUnitData is false. And by this assumption, they overwrite this variable. As it's allocated by malloc, this chunk of memory gets lost. For example, this is a trace from running unity8-dash under Valgrind: ==4360== 601,072 bytes in 96 blocks are definitely lost in loss record 1,495 of 1,495 ==4360== at 0x483E358: malloc (vg_replace_malloc.c:296) ==4360== by 0x4C3120B: QV4::Compiler::JSUnitGenerator::generateUnit(QV4::Compiler::JSUnitGenerator::GeneratorOption) (qv4compiler.cpp:221) ==4360== by 0x4C3CB8F: QV4::EvalInstructionSelection::compile(bool) (qv4isel_p.cpp:370) ==4360== by 0x4C6BE0F: QQmlTypeCompiler::compile() (qqmltypecompiler.cpp:223) ==4360== by 0x4D4AD7D: QQmlTypeData::compile() (qqmltypeloader.cpp:2359) .... (the rest is omitted as they're not relavant.) QQmlTypeCompiler::compile() in src/qml/compiler/qqmltypecompiler.cpp, line 201-233: // Compile JS binding expressions and signal handlers if (!document->javaScriptCompilationUnit) { (line 203-222 omitted) document->javaScriptCompilationUnit = isel->compile(/*generated unit data*/false); } // Generate QML compiled type data structures QmlIR::QmlUnitGenerator qmlGenerator; QV4::CompiledData::Unit *qmlUnit = qmlGenerator.generate(*document); Q_ASSERT(document->javaScriptCompilationUnit); // The js unit owns the data and will free the qml unit. document->javaScriptCompilationUnit->data = qmlUnit; You'll see that isel->compile() is called with generateUnitData set to false. Then, document->javaScriptCompilationUnit->data is set to the value of qmlUnit. This means that the old value of document->javaScriptCompilationUnit->data is overwritten without being freed properly. I think the solution is to free this memory at the end of EvalInstructionSelection::compile() if generateUnitData is false. All codes come from qtdeclarative-opensource-src version 5.4.1-1ubuntu11~overlay9~1 from stable-phone-overlay. ** Affects: qtdeclarative-opensource-src (Ubuntu) Importance: Undecided Status: New -- You received this bug notification because you are a member of Ubuntu Touch seeded packages, which is subscribed to qtdeclarative-opensource- src in Ubuntu. https://bugs.launchpad.net/bugs/1656851 Title: Memory leak in EvalInstructionSelection. Status in qtdeclarative-opensource-src package in Ubuntu: New Bug description: QV4::EvalInstructionSelection::compile(bool generateUnitData) in src/qml/compiler/qv4isel_p.cpp, line 369-370: if ((unit->data == nullptr) && (do_save || generateUnitData)) unit->data = jsGenerator->generateUnit(); Above this line, I see that do_save is always true. So, unit->data is always generated, regardless of the value of generateUnitData. However, by tracing to callers of this function, it's revealed that callers expect unit->data to be NULL if generateUnitData is false. And by this assumption, they overwrite this variable. As it's allocated by malloc, this chunk of memory gets lost. For example, this is a trace from running unity8-dash under Valgrind: ==4360== 601,072 bytes in 96 blocks are definitely lost in loss record 1,495 of 1,495 ==4360== at 0x483E358: malloc (vg_replace_malloc.c:296) ==4360== by 0x4C3120B: QV4::Compiler::JSUnitGenerator::generateUnit(QV4::Compiler::JSUnitGenerator::GeneratorOption) (qv4compiler.cpp:221) ==4360== by 0x4C3CB8F: QV4::EvalInstructionSelection::compile(bool) (qv4isel_p.cpp:370) ==4360== by 0x4C6BE0F: QQmlTypeCompiler::compile() (qqmltypecompiler.cpp:223) ==4360== by 0x4D4AD7D: QQmlTypeData::compile() (qqmltypeloader.cpp:2359) .... (the rest is omitted as they're not relavant.) QQmlTypeCompiler::compile() in src/qml/compiler/qqmltypecompiler.cpp, line 201-233: // Compile JS binding expressions and signal handlers if (!document->javaScriptCompilationUnit) { (line 203-222 omitted) document->javaScriptCompilationUnit = isel->compile(/*generated unit data*/false); } // Generate QML compiled type data structures QmlIR::QmlUnitGenerator qmlGenerator; QV4::CompiledData::Unit *qmlUnit = qmlGenerator.generate(*document); Q_ASSERT(document->javaScriptCompilationUnit); // The js unit owns the data and will free the qml unit. document->javaScriptCompilationUnit->data = qmlUnit; You'll see that isel->compile() is called with generateUnitData set to false. Then, document->javaScriptCompilationUnit->data is set to the value of qmlUnit. This means that the old value of document->javaScriptCompilationUnit->data is overwritten without being freed properly. I think the solution is to free this memory at the end of EvalInstructionSelection::compile() if generateUnitData is false. All codes come from qtdeclarative-opensource-src version 5.4.1-1ubuntu11~overlay9~1 from stable-phone-overlay. To manage notifications about this bug go to: https://bugs.launchpad.net/ubuntu/+source/qtdeclarative-opensource-src/+bug/1656851/+subscriptions -- Mailing list: https://launchpad.net/~touch-packages Post to : touch-packages@lists.launchpad.net Unsubscribe : https://launchpad.net/~touch-packages More help : https://help.launchpad.net/ListHelp