Segfaults con todas las declaraciones `if/else-if/else-if` pero no al comentar una de ellas

I have a tricky one here I just can't seem to figure out. When using the whole if/else-if/else-if it segfaults if the argument in the vector doesn't exist. If the argument exists then it runs fine it seems. When I comment out one of the else-if blocks then it runs ok it seems also.

Editado:

void
priority_arg_create (gchar *arg)
{
    gchar **argvp;
    gint argcp;
    gint i;
    gint j;

    argvp = get_arg_vector ();
    argcp = 0;
    i = 0;

    /* obtain arg count not including the `NULL` terminator. */
    while (argvp[argcp])
    {
        argcp++;
    }

    g_print ("From `rt_priority.c` line 42: %d\n", argcp);

    /* Here we look for the jack arg `-Px` with the for loop then the if
    statement. If it does not exist then we add it to arg vector with
    `else/if` statement. */
    for (i = 0; i <= argcp; i++)
    {
        if ((i == argcp -1) && (strncmp (argvp[i], "-P", 2) != 0))
        {
            g_print ("From `rt_priority.c` line 65\n");

            /* Add space to arg vector for the jackd arg `-R`. */
            argcp = argcp + 1;

            /* If realtime arg exists then place priority arg right
            after that.*/
            if ((strncmp (argvp[1], "-r", 2) == 0) ||
                (strncmp (argvp[1], "-R", 2) == 0))
            {
                /* Here we move the args over one to place `-Px` as the
                third arg in the vector. */
                for (j = argcp; j >= 2; j--)
                {
                    argvp[j] = argvp[j - 1];
                }

                argvp[2] = arg;
            }
            else
            {
                /* Here we move the args over one to place `-Px` as the
                second arg in the vector. */
                for (j = argcp; j >= 1; j--)
                {
                    argvp[j] = argvp[j - 1];
                }

                argvp[1] = arg;
            }

            break;
        }
        else if (g_strcmp0 (argvp[i], arg) == 0)
        {
            g_print ("From `rt_priority.c` line 51: %d\n", i);

            break;
        }
        /* If `priority arg` is found but the number does not match
        execute else/if statement. */
        else if (strncmp (argvp[i], "-P", 2) == 0)
        {              
            argvp[i] = arg;

            break;
        }
    }     
    file_input (argvp, argcp);
}

Y aquí está la salida de g_print () dentro de for () loop with line 56 demostración argvp y line 57 demostración argcp :

From `rt_priority.c` line 42: 6
From `rt_priority.c` line 56: /usr/bin/jackd
From `rt_priority.c` line 57: 6
From `rt_priority.c` line 56: -dalsa
From `rt_priority.c` line 57: 6
From `rt_priority.c` line 56: -dhw:M2496
From `rt_priority.c` line 57: 6
From `rt_priority.c` line 56: -r48000
From `rt_priority.c` line 57: 6
From `rt_priority.c` line 56: -p128
From `rt_priority.c` line 57: 6
From `rt_priority.c` line 56: -n2
From `rt_priority.c` line 57: 6
From `rt_priority.c` line 56: (null)
From `rt_priority.c` line 57: 6
Segmentation fault (core dumped)

Editado:

Este es el get_arg_vector () función:

gchar **argvp
get_arg_vector ()
{
    gchar cmd[128];
gchar **argvp;
gchar *contents;
gint argcp;
gsize size;

/* Create path to file `.jackdrc` using `g_sprintf ()`. */
g_sprintf (cmd, "%s/.jackdrc", g_getenv ("HOME"));

/* Check if file path exists. */
if (g_file_test (cmd, G_FILE_TEST_EXISTS) == FALSE)
{
    g_print ("File doesn't exist.  Create file.");

    return NULL;
}

g_file_get_contents (cmd, &contents, &size, NULL);
g_shell_parse_argv (contents, &argcp, &argvp, NULL);

return argvp;
}

preguntado el 28 de mayo de 14 a las 13:05

2 Respuestas

La última si no is supposed to resize the argvp-array when the end is reached in the para-bucle. El if y la primera si no read the current value from the argvp (which might be 0, which is an error). Probably the code started out containing only the last si no, y el otro if/else-ifs were inserted later. Change the order of the si no, so that the last runs before the other ones, then it should work.

To make space for one additional element in the array returned by get_arg_vector simply realloc it to contain one more element; i.e. just before returning the argvp, at the end of get_arg_vector, insert:

  ....
  argvp = g_realloc (argvp, (argcp + 2) * sizeof *argvp);
  return argvp;
}

The array normally contains (argcp+1) elements, so (argcp+2) makes it one element bigger.

contestado el 29 de mayo de 14 a las 00:05

I changed the order as suggested and I still get the segfault. I also changed the comparison in the first if () statement but again still same error. - Dru

Actually let me correct myself. I'm getting undefined behavior and sometimes get a corrupted double-linked list: 0x0000000001ddac20 error o realloc(): invalid pointer: 0x0000000001b7efc0 error. - Dru

The problem is likely with the get_arg_vector() function. For the code to work, it must return an array that is at least one element bigger than what is required; because it has to have enough space for the extra argument that is inserted. If it has not, the function will overwrite memory at the end of the array (which results in the error with the realloc() because malloc() puts its own data at the end). The line with the argcp = argcp + 1; in it, does not actually resize the array, it only treats it as a longer array, the array must be long enough for that already. - rassahah

rassahah: I added the get_arg_vector () function in OP. How would I add an element to the returned **argvp? I'm a little uncertain on how do this. - Dru

i augmented the answer on how to do that. - rassahah

Esta:

for (i = 0; i <= argcp + 1; i++)

is scary. We know that argv[argcp] is NULL, from the loop above that did the search. Thus, this loop oversteps that by dos, from using <= y + 1.

Print the current index as you loop, and also print the value of argcp.

contestado el 28 de mayo de 14 a las 13:05

Imprimir desde for () is above in OP. - Dru

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.