Environment: Ubuntu 11.04. SDL 1.2.15.
In my SDL based application, I play multiple video clips one after another. For each video, I call SDL_OpenAudio at the start and SDL_CloseAudio at the end. However, each round leaves two blocks of memory unfreed. Both of them are coming from internal SDL function AudioAvailable.
==17035== 372 bytes in 3 blocks are definitely lost in loss record 139 of 169
==17035== at 0x4C28F9F: malloc (vg_replace_malloc.c:236)
==17035== by 0xB2B0564: ??? (in /usr/lib/x86_64-linux-gnu/libxcb.so.1.1.0)
==17035== by 0xB2B062A: ??? (in /usr/lib/x86_64-linux-gnu/libxcb.so.1.1.0)
==17035== by 0xB2B01CA: xcb_connect_to_display_with_auth_info (in /usr/lib/x86_64-linux-gnu/libxcb.so.1.1.0)
==17035== by 0xCC650ED: pa_client_conf_from_x11 (in /usr/lib/x86_64-linux-gnu/libpulsecommon-1.0.so)
==17035== by 0xC9ED83E: pa_context_new_with_proplist (in /usr/lib/x86_64-linux-gnu/libpulse.so.0.13.4)
==17035== by 0xC7DD9F2: pa_simple_new (in /usr/lib/x86_64-linux-gnu/libpulse-simple.so.0.0.3)
==17035== by 0x418AED: Audio_Available (SDL_pulseaudio.c:235)
==17035== by 0x405893: SDL_AudioInit (SDL_audio.c:360)
==17035== by 0x404A79: SDL_InitSubSystem (SDL.c:105)
==17035== by 0x405E59: SDL_OpenAudio (SDL_audio.c:404)
I am wondering if there is something that I could be doing wrong in my code. I have verified that SDL_CloseAudio is indeed being called.
I'm not an expert on SDL or OpenGL by any means, but I think that most software will leak memory at one point or another. See this post for more info: Why does valgrind say basic SDL program is leaking memory?
On the bright side, SDL is only leaking 374 bytes, which is pennies compared to what most systems offer. It shouldn't make a big difference in the long run.
Related
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)
I am trying to reproduc a problem .
My c code giving SIGABRT , i traced it back to this line number :3174
https://elixir.bootlin.com/glibc/glibc-2.27/source/malloc/malloc.c
/* Little security check which won't hurt performance: the allocator
never wrapps around at the end of the address space. Therefore
we can exclude some size values which might appear here by
accident or by "design" from some intruder. We need to bypass
this check for dumped fake mmap chunks from the old main arena
because the new malloc may provide additional alignment. */
if ((__builtin_expect ((uintptr_t) oldp > (uintptr_t) -oldsize, 0)
|| __builtin_expect (misaligned_chunk (oldp), 0))
&& !DUMPED_MAIN_ARENA_CHUNK (oldp))
malloc_printerr ("realloc(): invalid pointer");
My understanding is that when i call calloc function memory get allocated when I call realloc function and try to increase memory area ,heap is not available for some reason giving SIGABRT
My another question is, How can I limit the heap area to some bytes say, 10 bytes to replicate the problem. In stackoverflow RSLIMIT and srlimit is mentioned but no sample code is mentioned. Can you provide sample code where heap size is 10 Bytes ?
How can I limit the heap area to some bytes say, 10 bytes
Can you provide sample code where heap size is 10 Bytes ?
From How to limit heap size for a c code in linux , you could do:
You could use (inside your program) setrlimit(2), probably with RLIMIT_AS (as cited by Ouah's answer).
#include <sys/resource.h>
int main() {
setrlimit(RLIMIT_AS, &(struct rlimit){10,10});
}
Better yet, make your shell do it. With bash it is the ulimit builtin.
$ ulimit -v 10
$ ./your_program.out
to replicate the problem
Most probably, limiting heap size will result in a different problem related to heap size limit. Most probably it is unrelated, and will not help you to debug the problem. Instead, I would suggest to research address sanitizer and valgrind.
I'm almost getting the handle of GHC cost centres.... it is an awesome idea, and you can actually fix memory leaks with their profiling tools. But my problem is that the information I'm getting in the .hp profiling is too truncated:
(1319)GHC.Conc.Signal.CAF 640
(1300)GHC.Event.Thread.CAF 560
(2679)hGetReplies/connect/c... 112
(2597)insideConfig/CAF:lvl2... 32
(1311)GHC.IO.Handle.FD.CAF 656
(2566)setLoggerLevels/confi... 208
(2571)configureLoggingToCon... 120
(2727)reply/Database.Redis.... 32
How do I know for example what is the full cost centre stack in (2566) or (2559)? Is there a tool for that or a command-line option?
Pass +RTS -L100 to your the program when you run it with profiling, and change 100 to whatever number of characters you want to see of your cost centres.
The documentation can be found in the GHC user guide, section “RTS options for heap profiling”.
So I tried to test whether the D garbage collector works properly by running this program on Windows.
DMD 2.057 and 2.058 beta both give the same result, whether or not I specify -release, -inline, -O, etc.
The code:
import core.memory, std.stdio;
extern(Windows) int GlobalMemoryStatusEx(ref MEMORYSTATUSEX lpBuffer);
struct MEMORYSTATUSEX
{
uint Length, MemoryLoad;
ulong TotalPhys, AvailPhys, TotalPageFile, AvailPageFile;
ulong TotalVirtual, AvailVirtual, AvailExtendedVirtual;
}
void testA(size_t count)
{
size_t[] a;
foreach (i; 0 .. count)
a ~= i;
//delete a;
}
void main()
{
MEMORYSTATUSEX ms;
ms.Length = ms.sizeof;
foreach (i; 0 .. 32)
{
testA(16 << 20);
GlobalMemoryStatusEx(ms);
stderr.writefln("AvailPhys: %s MiB", ms.AvailPhys >>> 20);
}
}
The output was:
AvailPhys: 3711 MiB
AvailPhys: 3365 MiB
AvailPhys: 3061 MiB
AvailPhys: 2747 MiB
AvailPhys: 2458 MiB
core.exception.OutOfMemoryError
When I uncommented the delete a; statement, the output was
AvailPhys: 3714 MiB
AvailPhys: 3702 MiB
AvailPhys: 3701 MiB
AvailPhys: 3702 MiB
AvailPhys: 3702 MiB
...
So I guess the question is obvious... does the GC actually work?
The problem here is false pointers. D's garbage collector is conservative, meaning it doesn't always know what's a pointer and what isn't. It sometimes has to assume that bit patterns that would point into GC-allocated memory if interpreted as pointers, are pointers. This is mostly a problem for large allocations, since large blocks are a bigger target for false pointers.
You're allocating about 48 MB each time you call testA(). In my experience this is enough to almost guarantee there will be a false pointer into the block on a 32-bit system. You'll probably get better results if you compile your code in 64-bit mode (supported on Linux, OSX and FreeBSD but not Windows yet) since 64-bit address space is much more sparse.
As far as my GC optimizations (I'm the David Simcha that CyberShadow mentions) there were two batches. One's been in for >6 months and hasn't caused any problems. The other is still in review as a pull request and isn't in the main druntime tree yet. These probably aren't the problem.
Short term, the solution is to manually free these huge blocks. Long term, we need to add precise scanning, at least for the heap. (Precise stack scanning is a much harder problem.) I wrote a patch to do this a couple years ago but it was rejected because it relied on templates and compile time function evaluation to generate pointer offset information for each datatype. Hopefully this information will eventually be generated directly by the compiler and I can re-create my precise heap scanning patch for the garbage collector.
This looks like a regression - it doesn't happen in D1 (DMD 1.069). David Simcha has been optimizing the GC lately, so it might have something to do with that. Please file a bug report.
P.S. If you rebuild Druntime with DFLAGS set to -debug=PRINTF in the makefile, you will get information on when the GC allocates/deallocates via console. :)
It does work. Current implementation just never releases memory to operating system. Though GC reuses acquired memory, so it's not a really a leak.
I have a curious memory leak, it seems that the library function to_unbounded_string is leaking!
Code snippets:
procedure Parse (Str : in String;
... do stuff...
declare
New_Element : constant Ada.Strings.Unbounded.Unbounded_String :=
Ada.Strings.Unbounded.To_Unbounded_String (Str); -- this leaks
begin
valgrind output:
==6009== 10,276 bytes in 1 blocks are possibly lost in loss record 153 of 153
==6009== at 0x4025BD3: malloc (vg_replace_malloc.c:236)
==6009== by 0x42703B8: __gnat_malloc (in /usr/lib/libgnat-4.4.so.1)
==6009== by 0x4269480: system__secondary_stack__ss_allocate (in /usr/lib/libgnat-4.4.so.1)
==6009== by 0x414929B: ada__strings__unbounded__to_unbounded_string (in /usr/lib/libgnat-4.4.so.1)
==6009== by 0x80F8AD4: syntax__parser__dash_parser__parseXn (token_parser_g.adb:35)
Where token_parser_g.adb:35 is listed above as the "-- this leaks" line.
Other info: Gnatmake version 4.4.5. gcc version 4.4 valgrind version valgrind-3.6.0.SVN-Debian, valgrind options -v --leak-check=full --read-var-info=yes --show-reachable=no
Any help or insights appreciated,
NWS.
Valgrind clearly says that there is possibly a memory leak. It doesn't necessarily mean there is one. For example, if first call to that function allocates a pool of memory that is re-used during the life time of the program but is never freed, Valgrind will report it as a possible memory leak, even though it is not, as this is a common practice and memory will be returned to OS upon process termination.
Now, if you think that there is a memory leak for real, call this function in a loop, and see it memory continues to grow. If it does - file a bug report or even better, try to find and fix the leak and send a patch along with a bug report.
Hope it helps.
Was trying to keep this to comments, but what I was saying got too long and started to need formatting.
In Ada string objects are generally assumed to be perfectly-sized. The language provies functions to return the size and bounds of any string. Because of this, string handling in Ada is very different than C, and in fact more resembles how you'd do it in a functional language like Lisp.
But the basic principle is that, except in some very unusual situations, if you find yourself using Ada.Strings.Unbounded, you are going about things the wrong way.
The one case where you really can't get around using a variable-length string (or perhaps a buffer with a separate valid_length variable), is when reading strings as input from some external source. As you say, your parsing example is such a situation.
However, even here you should only have that situation on the initial buffer. Your call to your Parse routine should look something like this:
Ada.Text_IO.Get_Line (Buffer, Buffer_Len);
Parse (Buffer(Buffer'first..Buffer'first + Buffer_Len - 1));
Now inside the Parse routine you have a perfectly-sized constant Ada string to work with. If for some reason you need to pull out a subslice, you would do the following:
... --// Code to find start and end indices of my subslice
New_Element : constant String := Str(Element_Start...Element_End);
If you don't actually need to make a copy of that data for some reason though, you are better off just finding Element_Start and Element_End and working with a slice of the original string buffer. Eg:
if Str(Element_Start..Element_End) = "MyToken" then
I know this doesn't answer your question about Ada.Strings.Unbounded possibly leaking. But even if it doesn't leak, that code is relatively wasteful of machine resources (CPU and memory), and probably shouldn't be used for string manipulation unless you really need it.
Are bound[ed] strings scoped?
Expanding on #T.E.D.'s comments, Ada.Strings.Bounded "objects should not be implemented by implicit pointers and dynamic allocation." Instead, the maximum size is fixed when the generic in instantiated. As an implmentation detail, GNAT uses a discriminant to specify the maximum size of the string and a record to store the current size & contents.
In contrast, Ada.Strings.Unbounded requires that "No storage associated with an Unbounded_String object shall be lost upon assignment or scope exit." As an implmentation detail, GNAT uses a buffered implementation derived from Ada.Finalization.Controlled. As a result, the memory used by an Unbounded_String may appear to be a leak until the object is finalized, as for example when the code returns to an enclosing scope.