Open kirill-21 opened 1 year ago
You're trying to free a different memory address than you allocate in this code.
Allocation:
Pointer<SystemProcessInformation> buffer = calloc<SystemProcessInformation>();
Or allocation:
calloc.free(buffer);
buffer = calloc<SystemProcessInformation>(dwSize.value);
Moving the pointer forward:
buffer = buffer
.cast<Uint8>()
.elementAt(buffer.ref.nextEntryOffset)
.cast<SystemProcessInformation>();
The pointer is now no longer the same pointer.
Freeing with a memory address that is somewhere inside the allocated buffer rather than at the beginning:
calloc.free(buffer);
I believe you should free with the original pointer, not with the one that is moved.
You're trying to free a different memory address than you allocate in this code.
Allocation:
Pointer<SystemProcessInformation> buffer = calloc<SystemProcessInformation>();
Or allocation:
calloc.free(buffer); buffer = calloc<SystemProcessInformation>(dwSize.value);
Moving the pointer forward:
buffer = buffer .cast<Uint8>() .elementAt(buffer.ref.nextEntryOffset) .cast<SystemProcessInformation>();
The pointer is now no longer the same pointer.
Freeing with a memory address that is somewhere inside the allocated buffer rather than at the beginning:
calloc.free(buffer);
I believe you should free with the original pointer, not with the one that is moved.
How do I do that? Can you test this code?
I tried to do this:
final int realBufferAddress = buffer.address;
// loop
buffer = Pointer.fromAddress(realBufferAddress); calloc.free(buffer);
This does not lead to a crash, however, according to memory view in taskmanager it's not released
So freeing with crash frees the memory and freeing without doesn't :c
Situation seems to be much better with malloc, memory is much more efficient , however, this still does not fully free the memory
buffer = Pointer.fromAddress(realBufferAddress); calloc.free(buffer);
👍
This does not lead to a crash, however, according to memory view in taskmanager it's not released
It should be, maybe there's another issue with the code? Are you allocating somewhere else?
Situation seems to be much better with malloc, memory is much more efficient , however, this still does not fully free the memory
Malloc should maybe be faster because the memory does not have to be zeroed out, but I'm not sure why it would lead to less memory usage.
Just looking at the task manager does not tell you what is holding on to the memory. Is it the Dart heap? Is it non-freed C memory? You could try using the memory view in devtools: https://docs.flutter.dev/tools/devtools/memory
buffer = Pointer.fromAddress(realBufferAddress); calloc.free(buffer);
👍
This does not lead to a crash, however, according to memory view in taskmanager it's not released
It should be, maybe there's another issue with the code? Are you allocating somewhere else?
Situation seems to be much better with malloc, memory is much more efficient , however, this still does not fully free the memory
Malloc should maybe be faster because the memory does not have to be zeroed out, but I'm not sure why it would lead to less memory usage.
Just looking at the task manager does not tell you what is holding on to the memory. Is it the Dart heap? Is it non-freed C memory? You could try using the memory view in devtools: https://docs.flutter.dev/tools/devtools/memory
I see that with calloc my process can go up to 5GB of memory usage, with malloc it's only 350MB. (Can be tested if looping this code in long while loop)
No, I'm testing it in the example I've provided, memory is not allocated anywhere else. I'll check devtools in the morning
Just looking at the task manager does not tell you what is holding on to the memory. Is it the Dart heap? Is it non-freed C memory? You could try using the memory view in devtools: https://docs.flutter.dev/tools/devtools/memory
Interesting, 4 GB of RSS (resident set size). That could be the C memory. @rmacnak-google @bkonyi does FFI malloc
ed memory show up in the RSS? I presume the "Dart/Flutter Native" only contains the runtime allocated memory, correct?
You could try wrapping your malloc
and free
calls to log which ones you are freeing. It seems very strange that malloc
and calloc
from package:ffi
would have different behavior in your application. On windows, they are backed by the same native allocator winCoTaskMemAlloc, so it's really unlikely that it would behave differently on the native side.
Linux: Usually malloc'd memory will be in RSS. Memory is part of RSS once it's been touched. Often a small allocation will be on the same page as malloc metadata or a small calloc allocation will be explicitly zeroed. But potentially a large malloc or calloc allocation gets a mmapped region to itself, and doesn't count toward RSS because it will be lazily paged in with zeroed pages.
Windows: I'm not sure whether the pages are brought in lazily or eagerly.
On Windows, we zero out the memory manually (CoTaskMemAlloc
doesn't have a zeroed out version), so that could move the memory in to the RSS if it works similarly on Windows.
@kirill-21 it might be that you're leaking native memory in your application forgetting to free
, but that with malloc
from package:ffi
it shows up less aggressively than with calloc
due to the above.
You could try wrapping your
malloc
andfree
calls to log which ones you are freeing.
This is your best bet to figuring out what's going on.
On Windows, we zero out the memory manually (
CoTaskMemAlloc
doesn't have a zeroed out version), so that could move the memory in to the RSS if it works similarly on Windows.@kirill-21 it might be that you're leaking native memory in your application forgetting to
free
, but that withmalloc
frompackage:ffi
it shows up less aggressively than withcalloc
due to the above.You could try wrapping your
malloc
andfree
calls to log which ones you are freeing.This is your best bet to figuring out what's going on.
If I free it my app crashes, if I free it with original pointer address then not all memory is released. Because when I do it with crashing and I can see in memory usage that it drops to ~200MB. With non-crash approach this value is at least twice bigger (with calloc)
This is the place where crash happens, if you remove this line then there will be no crash. And if this pointer is not freed then it leads to a huge memory leak