2009-11-28 32 views
5

Tôi đang sử dụng thư viện ffcall (cụ thể là gói avcall của ffcall) để tự động đẩy các tham số đến các hàm variadic. tức là chúng tôi cóvoid con trỏ và ffcall thư viện

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

và chúng tôi muốn gọi hàm này với các giá trị được lấy từ người dùng. Để làm điều này, chúng ta tạo ra một phiên bản avcall của hàm:

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

Bây giờ, chức năng Tôi đang sử dụng avcall với là:

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

Và nó được sử dụng như sau:

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

Nhưng tôi muốn sử dụng avcall để nắm bắt một số tiền nhất định của các giá trị từ chức năng này và tôi không biết thông tin này trước. Vì vậy, tôi nghĩ rằng tôi chỉ muốn tạo ra một mảng các con trỏ void và sau đó không gian malloc theo loại:

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 chỉ là:

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

Tôi đã được trải qua một loạt các bộ nhớ tham nhũng lỗi và có vẻ như nó không giống như những gì tôi đang làm ở đây. Tôi không thể phát hiện ra bất cứ điều gì sai trái với cách tôi đã làm điều này, bạn có thể? Tại thời điểm này, nó không thích nó khi tôi cố gắng giải phóng mallocs bên trong vòng lặp trong khi av_read_row. Bất cứ ai có thể nhìn thấy những gì tôi đang làm sai, nếu có gì?

Cảm ơn

+0

Tôi nghĩ rằng strcat của bạn thiếu một cái gì đó ... Tôi không thực sự quen thuộc với các công cụ av_, nhưng nếu printf_string là ghi đè bạn sẽ nhận được một số kết quả khó chịu. –

+1

Đây có phải là (http://www.haible.de/bruno/packages-ffcall.html) gói bạn đang sử dụng không? –

Trả lời

0

tôi đã không đi vào chi tiết tốt hơn của mã này, nhưng có thể nói như sau

  1. Sử dụng ngăn xếp để thông qua số lượng lớn các đối số là không nên, vì chồng bị hạn chế. Tôi không chắc chắn nếu av_stuff thực sự kiểm tra giới hạn stack.
  2. Không có phương pháp đơn giản hơn để thực hiện thao tác tương tự thay vì đẩy biến để ngăn xếp?
1

Thông tin duy nhất tôi có thể dễ dàng tìm thấy về avcall là từ năm 2001, nhưng đề xuất POSIX. Nếu bạn có thể chạy công cụ của bạn trên Linux, valgrind sẽ tìm thấy lỗi bộ nhớ của bạn trong nháy mắt. Đó là một công cụ tuyệt vời.

Các vấn đề liên quan