Opened 7 years ago
Closed 7 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 , 7 years ago
comment:2 by , 7 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 , 7 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 , 7 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?