Opened 6 years ago
Closed 6 years ago
#5406 closed defect (fixed)
Memory Leak in memory_pool
Reported by: | Owned by: | Lennart Ochel | |
---|---|---|---|
Priority: | high | Milestone: | Future |
Component: | Run-time | Version: | v1.14.0-dev-nightly |
Keywords: | Cc: |
Description
The following model leaks memory every time the function fmi2GetReal
is called:
model LeakyModel parameter Integer arraySize = 150; input Real[arraySize] inputArray; output Real[arraySize] outputArray; equation outputArray = functions.leakyCopy(arraySize, inputArray); end LeakyModel; package functions function leakyCopy input Integer s; input Real[s] arrayToCopy; output Real[s] copiedArray; algorithm copiedArray := arrayToCopy; end leakyCopy; end functions;
How to reproduce:
System: Ubuntu Linux 18.04 LTS
OpenModelica version: 1.13.2 and current dev (OMCompiler v1.14.0-dev.177+gb70342a5e) both show the same behavior
Build FMU via oms script:
loadModel(Modelica);getErrorString(); loadFiles(fileNames={"LeakyModel.mo"});getErrorString(); buildModelFMU(LeakyModel, platforms={"static"}, includeResources=true); getErrorString();
I used FMI4cpp to load the FMU and call fmi2SetReal
and fmi2GetReal
in a loop, like this:
int main() { fmi2Fmu fmu("../resources/LeakyModel.fmu"); auto me_fmu = fmu.asModelExchangeFmu(); auto md = me_fmu->getModelDescription(); logger::info("Name={}, start={}", var.name(), var.start().value_or(0)); auto slave = me_fmu->newInstance(); logger::info("modelIdentifier={}", slave->getModelDescription()->modelIdentifier); slave->enterInitializationMode(); slave->exitInitializationMode(); fmi4cpp::fmi4cppInteger arraySize; slave->readInteger(md->getVariableByName("arraySize").valueReference, arraySize); logger::info("The array is of size " + std::to_string(arraySize)); auto inReference = md->getVariableByName("inputArray[1]").valueReference; auto outReference = md->getVariableByName("outputArray[1]").valueReference; fmi4cpp::fmi4cppReal r; for(int i = 0; i < 1000000; ++i){ slave->writeReal(inReference, i); slave->readReal(outReference, r); logger::info("Read: " + std::to_string(r)); std::this_thread::sleep_for(10ms); } return 0; }
(The leak is small, but this model is just a trimmed down version to showcase the faulty behavior a bigger one I am using shows)
The valgrind output looks like this:
==26715== 62,914,560 bytes in 4 blocks are still reachable in loss record 148 of 148 ==26715== at 0x4C2FB0F: malloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so) ==26715== by 0x7901C7E: pool_expand (memory_pool.c:103) ==26715== by 0x7901C7E: pool_malloc (memory_pool.c:113) ==26715== by 0x7905480: alloc_real_array (real_array.c:85) ==26715== by 0x78315CD: omc_functions_leakyCopy (in /tmp/fmi4cpp_LeakyModel_17449512/binaries/linux64/LeakyModel.so) ==26715== by 0x7831375: LeakyModel_eqFunction_2 (in /tmp/fmi4cpp_LeakyModel_17449512/binaries/linux64/LeakyModel.so) ==26715== by 0x78318D1: LeakyModel_functionAlgebraics (in /tmp/fmi4cpp_LeakyModel_17449512/binaries/linux64/LeakyModel.so) ==26715== by 0x78131F1: fmi2GetReal (in /tmp/fmi4cpp_LeakyModel_17449512/binaries/linux64/LeakyModel.so) ==26715== by 0x150DF8: fmi4cpp::fmi2::fmi2Library::readReal(void*, unsigned int, double&) (fmi2Library.cpp:199) ==26715== by 0x156DDC: fmi4cpp::AbstractFmuInstance<fmi4cpp::fmi2::fmi2ModelExchangeLibrary, fmi4cpp::fmi2::ModelExchangeModelDescription>::readReal(unsigned int, double&) (AbstractFmuInstance.hpp:145) ==26715== by 0x11C803: main (fmu_test.cpp:75)
The memory pool just keeps getting bigger and bigger and I see no way to let the FMU clean up.
Am I doing something fundamentally wrong or is this a bad memory leak?
Change History (6)
comment:1 by , 6 years ago
comment:2 by , 6 years ago
Any news on this? If you can provide me with some pointers I might be able to come up with a solution myself and create a PR.
comment:3 by , 6 years ago
You can try the latest nightly builds and see if it works any better. There are a few changes in there.
comment:5 by , 6 years ago
@schmitz.basti, if the issue is solved for you, please close the ticket :)
Well, we should be able to call
omc_alloc_interface.collect_a_little
, which has a weird name but actually free's the pool. There is just one problem: if you instantiate multiple copies of the same FMU the global variable for the string pool will clear both of them (or if you have multiple OpenModelica FMUs and do a shallow loading of the shared objects).For regular simulations this is called once for every step.
@lochel: do you know where it would be (sort of) safe to add these calls in the exported FMU?