I have the following little Ada program:
procedure Leaky_Main is
task Beer;
task body Beer is
begin
null;
end Beer;
begin
null;
end Leaky_Main;
All fairly basic, but when i compile like this:
gnatmake -g -gnatwI leaky_main.adb
and run it through Valgrind like this :
valgrind --tool=memcheck -v --leak-check=full --read-var-info=yes --leak-check=full --show-reachable=yes ./leaky_main
I get the following error summary:
==2882== 2,104 bytes in 1 blocks are still reachable in loss record 1 of 1
==2882== at 0x4028876: malloc (vg_replace_malloc.c:236)
==2882== by 0x42AD3B8: __gnat_malloc (in /usr/lib/i386-linux-gnu/libgnat-4.4.so.1)
==2882== by 0x40615FF: system__task_primitives__operations__new_atcb (in /usr/lib/i386-linux-gnu/libgnarl-4.4.so.1)
==2882== by 0x406433C: system__tasking__initialize (in /usr/lib/i386-linux-gnu/libgnarl-4.4.so.1)
==2882== by 0x4063C86: system__tasking__initialization__init_rts (in /usr/lib/i386-linux-gnu/libgnarl-4.4.so.1)
==2882== by 0x4063DA6: system__tasking__initialization___elabb (in /usr/lib/i386-linux-gnu/libgnarl-4.4.so.1)
==2882== by 0x8049ADA: adainit (b~leaky_main.adb:142)
==2882== by 0x8049B7C: main (b~leaky_main.adb:189)
==2882==
==2882== LEAK SUMMARY:
==2882== definitely lost: 0 bytes in 0 blocks
==2882== indirectly lost: 0 bytes in 0 blocks
==2882== possibly lost: 0 bytes in 0 blocks
==2882== still reachable: 2,104 bytes in 1 blocks
==2882== suppressed: 0 bytes in 0 blocks
==2882==
==2882== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 21 from 6)
--2882--
--2882-- used_suppression: 21 U1004-ARM-_dl_relocate_object
==2882==
==2882== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 21 from 6)
Does anyone know why this is being reported as an error ?
Im fairly sure there is no actual leak, but i would like to know why/how it happens.
Thanks,
The problematic allocation looks to be the task control block (TCB). This has to be retained after the task has completed so that you can say
if Beer’Terminated then
...
so I think it’s probably an artefact of when valgrind does thecheck.
I’ve only come across this where the task was allocated; it was necessary to wait until ’Terminated was True before deallocating the task, or GNAT happily deallocated the stack but silently didn’t deallocate the TCB, leading to a real leak like yours. AdaCore recently fixed this (I don’t have the reference, it was on their developer log).
You should use deleaker for debugging. I prefer it)
Related
versions we are using
NodeOracleDb Version: 4.1.0 / 5.1.0/ 5.4.0
platform linux
version v18.1.0
arch x64
version 5.4.0
oracleclient 19.8.0.0.0 oracle
DB: 19.0.0.0.ru-2021-10.rur-2021-10.r1
Detailed Description
When we use a connection pool(max 30 min 10) and if we are fetching records from a table which has more than 250+ columns where few are clobs. The memory keeps on increasing and this memory increase is in RSS. This memory never comes down and the app crashes with OOM after a certain time. We were initially using the loopback 3 framework with oracle client, but we were able to simulate the same using the default connectionPool code given in the sample files (https://github.com/oracle/node-oracledb/blob/main/examples/connectionpool.js). What we were also able to find out was this was coming mainly when we are using connection pool.
Include a runnable Node.js script that shows the problem.
https://github.com/oracle/node-oracledb/files/9132973/oracleLeak.zip
This has insert script and create table scripts. Please run them first and then modify sample.js for DB connection.
We tested this with min pool as 10, max pool as 30 and UV_THREADPOOL_SIZE as 30
We even tried valgrind with 5.4.0 and we found that the issue is visible with definitely lost.
==36361== 903,607 (32,256 direct, 871,351 indirect) bytes in 1 blocks are definitely lost in loss record 4,608 of 4,615
==36361== at 0x4C03A83: calloc (in /usr/libexec/valgrind/vgpreload_memcheck-amd64-linux.so)
==36361== by 0x1181F179: njsConnection_executeAsync (in /home/ubuntu/hkfps/oepy-outbound-payment-all/node_modules/oracledb/build/Release/oracledb-5.4.0-linux-x64.node)
==36361== by 0x11819C24: njsBaton_executeAsync (in /home/ubuntu/hkfps/oepy-outbound-payment-all/node_modules/oracledb/build/Release/oracledb-5.4.0-linux-x64.node)
==36361== by 0x163C973: worker (threadpool.c:122)
==36361== by 0x58B2B42: start_thread (pthread_create.c:442)
==36361== by 0x5943BB3: clone (clone.S:100)
=36361== LEAK SUMMARY:
==36361== definitely lost: 32,256 bytes in 2 blocks
==36361== indirectly lost: 871,351 bytes in 975 blocks
==36361== possibly lost: 2,500,246 bytes in 1,397 blocks
==36361== still reachable: 485,525,664 bytes in 30,537 blocks
==36361== of which reachable via heuristic:
==36361== multipleinheritance: 48 bytes in 1 blocks
==36361== suppressed: 0 bytes in 0 blocks
Valgrind command which was used
valgrind --track-origins=yes --leak-check=full --trace-children=yes --log-file=out_%p.log --demangle=yes --error-limit=no --show-leak-kinds=all node test5.js
memory leak detected while render ass subtitle, i use libass to render in a official steps, i really don't know why this occured. and valgrind show the following information:
==13313== 3,158,599 (1,128 direct, 3,157,471 indirect) bytes in 1 blocks are definitely lost in loss record 111,141 of 111,141
==13313== at 0x4C33B25: calloc (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==13313== by 0x506C74B: ass_renderer_init (in /usr/lib/x86_64-linux-gnu/libass.so.9.0.2)
My embedded system runs Linux 3.10.14.
While running, my application prints out this message.
ERR: Memory overflow! free bytes=56000, bytes used=4040000, bytes to allocate=84000
But when I do "free", it seems I have enough free memory.
/ # free
total used free shared buffers
Mem: 27652 20788 6864 0 0
-/+ buffers: 20788 6864
Swap: 0 0 0
Any possible root cause of the error message?
Or how can I use free memory to the last 1 byte?
Please comment if I am missing any information.
Thank you!
According to the output of "free", we can see totally there are 27652 bytes, 20788 bytes are used and 6864 bytes are free.
The print from your application, it seems to try to allocate 84000 bytes, but there are only 56000 bytes available。
So there is a question that how much memory do your system have? 27652 bytes or
4096000 bytes?
The printout is got from the system ?
I have lots of memory allocated in my mono droid program which doesn't appear to directly belong to either the Dalvik or the Mono heaps. Also, I can't figure out how to track .NET memory leaks.
When I call
adb shell dumpsys meminfo MyProgram.Droid
This is the output:
** MEMINFO in pid 1364 [MyProgram.Droid] **
Shared Private Heap Heap Heap
Pss Dirty Dirty Size Alloc Free
------ ------ ------ ------ ------ ------
Native 36 24 36 38080 37775 124
Dalvik 6934 15164 6572 16839 15384 1455
Cursor 0 0 0
Ashmem 0 0 0
Other dev 4 36 0
.so mmap 12029 2416 9068
.jar mmap 0 0 0
.apk mmap 16920 0 0
.ttf mmap 3 0 0
.dex mmap 2299 296 8
Other mmap 64 24 36
Unknown 28920 8216 28728
TOTAL 67209 26176 44448 54919 53159 1579
I assume that the "Unknown" section is the mono framework, including the .NET heap. However when I call
GC.GetTotalMemory(true)
It tells me that only 5Mb of memory is allocated. That leaves 23Mb which I cannot trace (and there's 38Mb of allocated native heap)
Additionally, I don't see that Xamarin have any tools for tracking .NET memory leaks. I've added garbage collection logging with
adb shell setprop debug.mono.log gc,gref
But this is incredibly verbose and hard to read and doesn't even include allocation sizes.
At this point I don't know what to do to track down the resulting leaks. Since the allocations appear to be on the native heap, do I need to use the NDK in order to track down what's going on? Are there any tools I can use on the C# side to track the .NET leaks?
Thanks!
Here's my code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char buf1[100];
char buf2[100];
int main()
{
char **p = (char**)(buf1+sizeof(long));
char **q = (char**)(buf2+1);
*p = (char*)malloc(100);
*q = (char*)malloc(100);
strcpy(*p, "xxxx");
strcpy(*q, "zzzz");
printf("p:%s q:%s\n", *p, *q);
return 0;
}
I compiled the code using gcc, and run valgrind-3.6.1 like this
valgrind --leak-check=full --log-file=test.log --show-reachable=yes ~/a.out
valgrind gave me the log below
==20768== Memcheck, a memory error detector
==20768== Copyright (C) 2002-2010, and GNU GPL'd, by Julian Seward et al.
==20768== Using Valgrind-3.6.1 and LibVEX; rerun with -h for copyright info
==20768== Command: /home/zxin11/a.out
==20768== Parent PID: 12686
==20768==
==20768==
==20768== HEAP SUMMARY:
==20768== in use at exit: 200 bytes in 2 blocks
==20768== total heap usage: 2 allocs, 0 frees, 200 bytes allocated
==20768==
==20768== 100 bytes in 1 blocks are still reachable in loss record 1 of 2
==20768== at 0x4C2488B: malloc (vg_replace_malloc.c:236)
==20768== by 0x4005FD: main (test2.c:12)
==20768==
==20768== 100 bytes in 1 blocks are definitely lost in loss record 2 of 2
==20768== at 0x4C2488B: malloc (vg_replace_malloc.c:236)
==20768== by 0x400611: main (test2.c:13)
==20768==
==20768== LEAK SUMMARY:
==20768== definitely lost: 100 bytes in 1 blocks
==20768== indirectly lost: 0 bytes in 0 blocks
==20768== possibly lost: 0 bytes in 0 blocks
==20768== still reachable: 100 bytes in 1 blocks
==20768== suppressed: 0 bytes in 0 blocks
==20768==
==20768== For counts of detected and suppressed errors, rerun with: -v
==20768== ERROR SUMMARY: 1 errors from 1 contexts (suppressed: 3 from 3)
Why the first malloc was still reachable while the second malloc was definitely lost?
Maybe it's about alignment, you can't put the address of malloced memory into an un-aligned variable, if so, how can I suppress this kind of positive report?
Think you very much.
From the memcheck manual (emphasis mine):
If --leak-check is set appropriately, for each remaining block, Memcheck determines if the block is reachable from pointers within the root-set. The root-set consists of (a) general purpose registers of all threads, and (b) initialised, aligned, pointer-sized data words in accessible client memory, including stacks.
So your conjecture about alignment was correct. Unfortunately, the best way to robustly suppress such a warning is probably just to copy any such known values into aligned locations before exiting your program (presumably this code is a mock-up for your real application, where it makes some sort of sense for you to store unaligned pointers).
You can also try writing or generating a suppression file with --gen-suppressions=yes. But if your application is non-deterministic or you run it with different input data, this approach will get annoying pretty quickly.