Search code examples
cuwppjsippjsua2

Dynamic array unknown size C


I have been working with pjsip for a while now, and in an effort to get it to work for UWP, I have encountered a seemingly fatal flaw in the base C code. I am getting errors 'addrs': unknown size and 'deprecatedAddrs': unknown size in the code below.

PJ_DEF(pj_status_t) pj_enum_ip_interface2( const pj_enum_ip_option *opt,
                       unsigned *p_cnt,
                       pj_sockaddr ifs[]) {
    pj_enum_ip_option opt_;

    if (opt)
    opt_ = *opt;
    else
    pj_enum_ip_option_default(&opt_);

    if (opt_.af != pj_AF_INET() && opt_.omit_deprecated_ipv6) {
    pj_sockaddr addrs[*p_cnt];
    pj_sockaddr deprecatedAddrs[*p_cnt];
    unsigned deprecatedCount = *p_cnt;
    unsigned cnt = 0;
    int i;
    pj_status_t status;
...

The error comes for the two lines pj_sockaddr addrs[*p_cnt]; and pj_sockaddr deprecatedAddrs[*p_cnt]; . I feel that I understand that this should not work, due to the fact that C cannot have dynamic arrays and needs to preallocate space. However, pjsip is a well-established library used rather often, so my question is: Is there a situation in which this would function at all?


Solution

  • This is valid c99 syntax. It's called a variable-length array. You might want to add the -std=c99 flag to your compiler.

    EDIT: Given the comments below, here's an example on how to use dynamic memory to replace VLAs.

    PJ_DEF(pj_status_t) pj_enum_ip_interface2( const pj_enum_ip_option *opt,
                           unsigned *p_cnt,
                           pj_sockaddr ifs[]) {
        pj_enum_ip_option opt_;
    
        if (opt)
        opt_ = *opt;
        else
        pj_enum_ip_option_default(&opt_);
    
        if (opt_.af != pj_AF_INET() && opt_.omit_deprecated_ipv6) {
        
        /* Dynamically allocate memory to replace VLAs
         * Use calloc if you need it initialized to zero
         */ 
        pj_sockaddr *addrs = malloc((*p_cnt) * sizeof (pj_sockaddr));
        pj_sockaddr *deprecatedAddrs = malloc((*p_cnt) * sizeof (pj_sockaddr));
        
        unsigned deprecatedCount = *p_cnt;
        unsigned cnt = 0;
        int i;
        pj_status_t status;
    
        ...
    
    
        /* Remember that memory allocated from the heap needs to be freed */
        free (addrs);
        free (deprecatedAddrs);
        
        /* Not needed, but a good practice */
        addrs = NULL; 
        deprecatedAddrs = NULL;
    
        ...
        
        return status;