2009-11-28 23 views
5

Değişken işlevlere dinamik olarak parametreleri itmek için ffcall (özellikle fccall'ın avcall paketi) kütüphanesini kullanıyorum. yanivoid işaretçiler ve ffcall kitaplığı

ve bu işlevi kullanıcıdan alınan değerlerle çağırmak istiyoruz. Bunu yapmak için, biz fonksiyonun bir avcall sürümünü oluşturmak:

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

Ve şöyle kullanılır:: Artık

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

, beraber avcall kullanıyorum fonksiyonudur

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

Ancak bu işlevden belirli bir miktar değer yakalamak için avcall kullanmak istiyorum ve bu bilgiyi önceden bilmiyorum. Yani ben sadece türüne göre bir boşluk işaretçiler dizisi ve ardından malloc alan oluşturmak düşündüm:

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

Ve av_read_row adildir:

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

Ben bellek bozulması nedeniyle bir demet yaşanmaktadır hatalar ve burada yaptığım şeyden hoşlanmıyormuş gibi görünüyor. Bunu yaptığım gibi yanlış bir şey tespit edemem, değil mi? Şu anda, döngü sırasında av_read_row içerisindeki malloları boşaltmaya çalıştığımda hoşlanmıyor. Bir şeyleri yanlış yaptığımı gören var mı? Yığın sınırlıdır olarak

Teşekkür

+0

Sanırım senin strcat'in bir şey eksik ... Av_ şeyler hakkında çok aşina değilim, ama eğer printf_string üzerine yazıyorsa, bazı kötü sonuçlar alacaksınız. –

+1

Kullanmakta olduğunuz paket bu mu (http://www.haible.de/bruno/packages-ffcall.html)? –

cevap

0

ben kod ince detaya gitmedi, ama

  1. aşağıdaki değişkenlerden sayıda geçirilmesi için yığın Kullanma söyleyebiliriz, tavsiye edilmez. Av_stuff'ın yığın sınırını gerçekten kontrol edip etmediğinden emin değilim.
  2. Değişkenleri yığmak yerine aynı işlemi yapmak için daha basit bir yöntem yok mu?
1

avcall hakkında kolayca bulabildiğim tek bilgi 2001'den beri, ancak POSIX'i önerir. Eşyalarınızı Linux'ta çalıştırabiliyorsanız, valgrind bellek arızalarınızı bir jiffy'de bulacaktır. Müthiş bir alet.