J'utilise la bibliothèque ffcall (en particulier la bibliothèque avcall de ffcall) pour pousser dynamiquement les paramètres vers les fonctions variadiques. c'est-à-dire que nous avonspointeurs de void et bibliothèque ffcall
int blah (char *a, int b, double c, ...);
et nous voulons appeler cette fonction avec des valeurs tirées de l'utilisateur. Pour ce faire, nous créons une version avcall de la fonction:
int av_blah (char *a, int b, double c, char **values, int num_of_values)
{
av_alist alist;
int i, ret;
av_start_int (alist, &blah, &ret); //let it know which function
av_ptr (alist, char*, a); // push values onto stack starting from left
av_int (alist, b);
av_double (alist, c);
for (i=0;i<num_of_values;i++)
{
// do what you want with values and add to stack
}
av_call (alist); //call blah()
return (ret);
}
Maintenant, la fonction que je me sers avcall avec est:
int read_row (struct some_struct *a, struct another_struct *b[], ...);
Et il est utilisé comme ceci:
struct some_struct a;
struct another_struct **b = fill_with_stuff();
char name[64];
int num;
while (read_row (&a, b, name, &num)==0)
{
printf ("name=%s, num=%d\n", name, num);
}
Mais je veux utiliser avcall pour capturer une certaine quantité de valeurs de cette fonction et je ne connais pas cette information à l'avance. Donc, je pensais que je venais de créer un tableau de pointeurs vides et l'espace de malloc en fonction du type:
char printf_string[64]=""; //need to build printf string inside av_read_row()
void **vals = Calloc (n+1, sizeof (void*)); //wrapper
while (av_read_row (&a, b, vals, n, printf_string) == 0)
{
// vals should now hold the values i want
av_printf (printf_string, vals, n); //get nonsense output from this
// free the mallocs which each vals[i] is pointing to
void **ptrs = vals;
while (*ptrs) {
free (*ptrs); //seg faults on first free() ?
*ptrs=NULL;
ptrs++;
}
//reset printf_string
printf_string[0]='\0';
printf ("\n");
}
Et av_read_row
est juste:
int av_read_row (struct some_struct *a, struct another_struct *b[], void **vals, int num_of_args, char *printf_string)
{
int i, ret;
av_alist alist;
av_start_int (alist, &read_row, &ret);
av_ptr (alist, struct some_struct *, a);
av_ptr (alist, struct another_struct **, b);
for (i=0;i<num_of_args;i++)
{
switch (type) //for simplicity
{
case INT: {
vals[i] = Malloc (sizeof (int));
av_ptr (alist, int*, vals[i]);
strcat (printf_string, "%d, ");
break;
}
case FLOAT: {
//Same thing
}
//etc
}
}
av_call (alist);
return (ret);
}
J'ai connu un tas de corruption de mémoire erreurs et il semble que ça n'aime pas ce que je fais ici. Je ne peux rien voir de faux avec la façon dont j'ai fait ça, n'est-ce pas? À l'heure actuelle, il n'aime pas quand je tente de libérer les mallocs à l'intérieur de la boucle av_read_row
. Quelqu'un peut-il voir ce que je fais mal, si quelque chose?
Merci
Je pense que votre strcat manque quelque chose ... Je ne suis pas vraiment familier avec le truc av_, mais si printf_string est écrasé, vous obtiendrez des résultats désagréables. –
Est-ce (http://www.haible.de/bruno/packages-ffcall.html) le paquet que vous utilisez? –