Search code examples
c++listfreeasn.1

How to correctly use and free asn1c SEQUENCE_OF?


I'm using the asn1c lib for many projects, but I never found how to use the free member of a SEQUENCE_OF. I always set it to nullptr because of that, and when I use Valgrind, I see (of course) that my lists members are not freed when using ASN_STRUCT_FREE on the element containing the list.

So my question is how can I use that free member?

Here is a simple example of how I use my lists with asn1c.

ListItem_t *li = nullptr;
StructWList_t swl;

swl.list.count = 0;
swl.list.size = 0;
swl.list.free = nullptr; // How can I feed it properly?
swl.list.array = reinterpret_cast<ListItem_t**>(calloc(1, sizeof *swl.list.array));

for(int i = 0 ; i < 5 ; i++)
{
    li = reinterpret_cast<ListItem_t*>(calloc(1, sizeof *li));
    *li = i;
    // Valgrind says that the calloc below is definitly lost
    swl.list.array[i] = reinterpret_cast<ListItem_t*>(calloc(1, sizeof *swl.list.array[i]));
    ASN_SEQUENCE_ADD(&swl, li);
}
...
ASN_STRUCT_FREE(ASN_DEF_StructWList, &swl);

Does anyone know how to feed it properly?

EDIT

My version of asn1c is the v0.9.29 from git repository in AUR (on Archlinux).

The above ASN.1 is as follow:

Example 
DEFINITIONS AUTOMATIC TAGS ::= 
BEGIN 

StructWList ::= SEQUENCE OF ListItem 
ListItem ::= INTEGER 
END

Thanks in advance,

Emilien


Solution

  • // Valgrind says that the calloc below is definitly lost
    swl.list.array[i] = reinterpret_cast<ListItem_t*>(calloc(1, sizeof *swl.list.array[i]));
    ASN_SEQUENCE_ADD(&swl, li);
    

    The ASN_SEQUENCE_ADD will overwrite the pointer you stored on the previous line. You should either store it manually as on the first line or call ASN_SEQUENCE_ADD but not both.

    Also you should fully initialize swl as it contains more members (_asn_ctx) and use ASN_STRUCT_FREE_CONTENTS_ONLY as swl is allocated on the stack and cannot be freed.

    --- main.cpp.orig   2019-05-07 20:49:25.880336931 +0300
    +++ main.cpp    2019-05-07 20:59:10.192431926 +0300
    @@ -3,7 +3,7 @@
     int main()
     {
        ListItem_t *li = nullptr;
    -   StructWList_t swl;
    +   StructWList_t swl = {0};
    
        swl.list.count = 0;
        swl.list.size = 0;
    @@ -15,8 +15,8 @@
            li = reinterpret_cast<ListItem_t*>(calloc(1, sizeof *li));
            *li = i;
            // Valgrind says that the calloc below is definitly lost
    -       swl.list.array[i] = reinterpret_cast<ListItem_t*>(calloc(1, sizeof *swl.list.array[i]));
    +       //swl.list.array[i] = reinterpret_cast<ListItem_t*>(calloc(1, sizeof *swl.list.array[i]));
            ASN_SEQUENCE_ADD(&swl, li);
        }
    -   ASN_STRUCT_FREE(ASN_DEF_StructWList, &swl);
    +   ASN_STRUCT_FREE_CONTENTS_ONLY(asn_DEF_StructWList, &swl);
     }
    

    Compile with g++ -Wall -I. -ggdb -O0 -o test main.cpp libasncodec.a

    valgrind --tool=memcheck ./test 
    ==29555== Memcheck, a memory error detector
    ==29555== Copyright (C) 2002-2017, and GNU GPL'd, by Julian Seward et al.
    ==29555== Using Valgrind-3.14.0 and LibVEX; rerun with -h for copyright info
    ==29555== Command: ./test
    ==29555== 
    ==29555== 
    ==29555== HEAP SUMMARY:
    ==29555==     in use at exit: 0 bytes in 0 blocks
    ==29555==   total heap usage: 9 allocs, 9 frees, 72,848 bytes allocated
    ==29555== 
    ==29555== All heap blocks were freed -- no leaks are possible
    ==29555== 
    ==29555== For counts of detected and suppressed errors, rerun with: -v
    ==29555== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 0 from 0)