5

我正在使用 ffcall(特别是 ffcall 的 avcall 包)库将参数动态推送到可变参数函数。即我们有

int blah (char *a, int b, double c, ...);

我们想用从用户那里获取的值来调用这个函数。为此,我们创建了该函数的 avcall 版本:

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);
}

现在,我使用 avcall 的函数是:

int read_row (struct some_struct *a, struct another_struct *b[], ...);

它是这样使用的:

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);
}

但是我想使用 avcall 从这个函数中捕获一定数量的值,我事先并不知道这些信息。所以我想我只是创建一个 void 指针数组,然后根据类型创建 malloc 空间:

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");
}

而且av_read_row只是:

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);
}

我遇到了一堆内存损坏错误,似乎它不喜欢我在这里做的事情。我无法发现我这样做的方式有什么问题,你可以吗?av_read_row目前,当我尝试在while 循环中释放 malloc 时,它不喜欢它。谁能看到我做错了什么,如果有的话?

谢谢

4

2 回答 2

1

我可以轻松找到的唯一信息avcall是 2001 年的,但它确实建议使用 POSIX。如果你可以在 Linux 上运行你的东西,valgrind很快就会发现你的内存故障。这是一个很棒的工具。

于 2010-01-17T06:23:32.800 回答
0

我没有进入代码的更详细的细节,但可以说以下

  1. 不建议使用堆栈来传递大量参数,因为堆栈是有限的。我不确定 av_stuff 是否真的检查堆栈限制。
  2. 难道没有更简单的方法来执行相同的操作而不是将变量推入堆栈吗?
于 2010-01-15T08:35:28.470 回答