• Uncategorized

About linux : alsa—mem-leak

Question Detail

I’ve been chasing a memory leak (reported by ‘valgrind –leak-check=yes’) and it appears to be coming from ALSA. This code has been in the free world for some time so I’m guessing that it’s something I’m doing wrong.

#include <stdio.h>
#include <stdlib.h>
#include <alsa/asoundlib.h>

int main (int argc, char *argv[])
{
    snd_ctl_t *handle;

    int err = snd_ctl_open( &handle, "hw:1", 0 );
    printf( "snd_ctl_open: %d\n", err );

    err = snd_ctl_close(handle);
    printf( "snd_ctl_close: %d\n", err );
}

The output looks like this:

[[email protected] alsa]# valgrind --leak-check=yes ./test2
==16296== Memcheck, a memory error detector
==16296== Copyright (C) 2002-2012, and GNU GPL'd, by Julian Seward et al.
==16296== Using Valgrind-3.8.1 and LibVEX; rerun with -h for copyright info
==16296== Command: ./test2
==16296==
snd_ctl_open: 0
snd_ctl_close: 0
==16296==
==16296== HEAP SUMMARY:
==16296==     in use at exit: 22,912 bytes in 1,222 blocks
==16296==   total heap usage: 1,507 allocs, 285 frees, 26,236 bytes allocated
==16296==
==16296== 4 bytes in 2 blocks are possibly lost in loss record 1 of 62
==16296==    at 0x4007100: malloc (vg_replace_malloc.c:270)
==16296==    by 0x340F7F: strdup (in /lib/libc-2.5.so)
==16296==    by 0x624C6B5: ??? (in /lib/libasound.so.2.0.0)
==16296==    by 0x624CA5B: ??? (in /lib/libasound.so.2.0.0)
==16296==    by 0x624CD81: ??? (in /lib/libasound.so.2.0.0)
==16296==    by 0x624F311: snd_config_update_r (in /lib/libasound.so.2.0.0)
==16296==    by 0x624FAD7: snd_config_update (in /lib/libasound.so.2.0.0)
==16296==    by 0x625DA22: snd_ctl_open (in /lib/libasound.so.2.0.0)
==16296==    by 0x804852F: main (test2.cpp:9)

and continues for some pages to

==16296== 2,052 bytes in 57 blocks are possibly lost in loss record 62 of 62
==16296==    at 0x4005EB4: calloc (vg_replace_malloc.c:593)
==16296==    by 0x624A268: ??? (in /lib/libasound.so.2.0.0)
==16296==    by 0x624A38F: ??? (in /lib/libasound.so.2.0.0)
==16296==    by 0x624CA33: ??? (in /lib/libasound.so.2.0.0)
==16296==    by 0x624CCC9: ??? (in /lib/libasound.so.2.0.0)
==16296==    by 0x624CD81: ??? (in /lib/libasound.so.2.0.0)
==16296==    by 0x624F311: snd_config_update_r (in /lib/libasound.so.2.0.0)
==16296==    by 0x624FAD7: snd_config_update (in /lib/libasound.so.2.0.0)
==16296==    by 0x625DA22: snd_ctl_open (in /lib/libasound.so.2.0.0)
==16296==    by 0x804852F: main (test2.cpp:9)
==16296==
==16296== LEAK SUMMARY:
==16296==    definitely lost: 0 bytes in 0 blocks
==16296==    indirectly lost: 0 bytes in 0 blocks
==16296==      possibly lost: 22,748 bytes in 1,216 blocks
==16296==    still reachable: 164 bytes in 6 blocks
==16296==         suppressed: 0 bytes in 0 blocks
==16296== Reachable blocks (those to which a pointer was found) are not shown.
==16296== To see them, rerun with: --leak-check=full --show-reachable=yes
==16296==
==16296== For counts of detected and suppressed errors, rerun with: -v
==16296== ERROR SUMMARY: 56 errors from 56 contexts (suppressed: 19 from 8)

This came about as I’m using ALSA in a project and started seeing this huge leak…or at least the report of said leak.

So the question is: is it me, ALSA or valgrind that’s having issues here?

Question Answer

http://git.alsa-project.org/?p=alsa-lib.git;a=blob;f=MEMORY-LEAK;hb=HEAD says:

                          Memory leaks - really?
                          ----------------------

Note that some developers are thinking that the ALSA library has some memory
leaks. Sure, it can be truth, but before contacting us, please, be sure that
these leaks are not forced.

The biggest reported leak is that the global configuration is cached for
next usage. If you do not want this feature, simply, call
snd_config_update_free_global() after all snd_*_open*() calls. This function
will free the cache.

The biggest reported leak is that the global configuration is cached for next usage.

If you do not want this feature, simply call snd_config_update_free_global() after all snd_*_open*() calls.

This function will free the cache.” <—- Valgrind still detects leaks.

This can be fixed if you call snd_config_update_free_global() after snd_pcm_close(handle);

Perhaps this will work (source):

diff --git a/src/pcm/pcm.c b/src/pcm/pcm.c

--- a/src/pcm/pcm.c
+++ b/src/pcm/pcm.c
@@ -2171,7 +2171,12 @@ static int snd_pcm_open_conf(snd_pcm_t **pcmp, const char *name,
        if (open_func) {
                err = open_func(pcmp, name, pcm_root, pcm_conf, stream, mode);
                if (err >= 0) {
-                       (*pcmp)->open_func = open_func;
+                       if ((*pcmp)->open_func) {
+                               /* only init plugin (like empty, asym) */
+                               snd_dlobj_cache_put(open_func);
+                       } else {
+                               (*pcmp)->open_func = open_func;
+                       }
                        err = 0;
                } else {
                        snd_dlobj_cache_put(open_func);

I tried it myself, but to no avail. My core temp heats up ~10 °F, most likely due to similar memory leak. Here’s some of what valgrind gave me, even after using the patch above:

    ==869== 16,272 bytes in 226 blocks are possibly lost in loss record 103 of 103
    ==869==    at 0x4C28E48: calloc (vg_replace_malloc.c:566)
    ==869==    by 0x5066E61: _snd_config_make (in /usr/lib64/libasound.so.2)
    ==869==    by 0x5066F58: _snd_config_make_add (in /usr/lib64/libasound.so.2)
    ==869==    by 0x50673B9: parse_value (in /usr/lib64/libasound.so.2)
    ==869==    by 0x50675DE: parse_array_def (in /usr/lib64/libasound.so.2)
    ==869==    by 0x5067680: parse_array_defs (in /usr/lib64/libasound.so.2)
    ==869==    by 0x5067A8E: parse_def (in /usr/lib64/libasound.so.2)
    ==869==    by 0x5067BC7: parse_defs (in /usr/lib64/libasound.so.2)
    ==869==    by 0x5067A6F: parse_def (in /usr/lib64/libasound.so.2)
    ==869==    by 0x5067BC7: parse_defs (in /usr/lib64/libasound.so.2)
    ==869==    by 0x5067A6F: parse_def (in /usr/lib64/libasound.so.2)
    ==869==    by 0x5067BC7: parse_defs (in /usr/lib64/libasound.so.2)

The number of bytes lost just keeps going up and up.

You may also like...

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.