2010-11-16 37 views
1

J'écris un programme dans le D qui utilise svn et je suis tombé sur quelque chose que je n'arrive pas à comprendre comment convertir en syntaxe D. J'ai pris un coup de couteau, mais ça se grave.Ajouter tableau en utilisant apr_array_push dans D

Exemple de ce que je suis en train d'accomplir en C:

svn_auth_provider_object_t provider; 
providers = apr_array_make(pool, 1, sizeof(svn_auth_provider_object_t*)); 
svn_auth_get_simple_provider2(&provider, null, null, pool); 
*(svn_auth_provider_object_t**)apr_array_push (providers) = provider; 
svn_auth_open(&auth_baton, providers, pool); 

Pour autant que je sache, ce code fonctionne très bien. J'ai trouvé plusieurs exemples faits presque exactement de la même manière. Voici ma tentative de copier ceci dans D:

svn_auth_provider_object_t provider; 
providers = apr_array_make(pool, 1, svn_auth_provider_object_t.sizeof); 
svn_auth_get_simple_provider2(&provider, null, null, pool); 
void* newSlot = apr_array_push(m); 
newSlot = provider; 
svn_auth_open(&auth_baton, providers, pool); 

Cela jette une erreur de segmentation sur svn_auth_open. Ma meilleure estimation est que le contenu du fournisseur ne se termine pas au pointeur détenu par newSlot. Et je ne suis pas sûr de savoir pourquoi.

Code supplémentaire:

/// Code taken from Apache's APR libary which is licensed under Apache License, Version 2.0 

struct apr_array_header_t { 
    apr_pool_t* pool; 
    int elt_size; 
    int nelts; 
    int nalloc; 
    char* elts; 
}; 

struct svn_auth_provider_object_t 
{ 
    svn_auth_provider_t *vtable; 
    void *provider_baton; 
} 

APR_DECLARE(void *) apr_array_push(apr_array_header_t *arr) 
{ 
    if (arr->nelts == arr->nalloc) { 
     int new_size = (arr->nalloc <= 0) ? 1 : arr->nalloc * 2; 
     char *new_data; 

     new_data = apr_palloc(arr->pool, arr->elt_size * new_size); 

     memcpy(new_data, arr->elts, arr->nalloc * arr->elt_size); 
     memset(new_data + arr->nalloc * arr->elt_size, 0, 
       arr->elt_size * (new_size - arr->nalloc)); 
     arr->elts = new_data; 
     arr->nalloc = new_size; 
    } 

    ++arr->nelts; 
    return arr->elts + (arr->elt_size * (arr->nelts - 1)); 
} 

#define APR_ARRAY_IDX(ary,i,type) (((type *)(ary)->elts)[i]) 
#define APR_ARRAY_PUSH(ary,type) (*((type *)apr_array_push(ary))) 

void 
svn_auth_open(svn_auth_baton_t **auth_baton, 
       apr_array_header_t *providers, 
       apr_pool_t *pool) 
{ 
    svn_auth_baton_t *ab; 
    svn_auth_provider_object_t *provider; 
    int i; 

    /* Build the auth_baton. */ 
    ab = apr_pcalloc(pool, sizeof(*ab)); 
    ab->tables = apr_hash_make(pool); 
    ab->parameters = apr_hash_make(pool); 
    ab->creds_cache = apr_hash_make(pool); 
    ab->pool = pool; 

    /* Register each provider in order. Providers of different 
    credentials will be automatically sorted into different tables by 
    register_provider(). */ 
    for (i = 0; i < providers->nelts; i++) 
    { 
     provider_set_t *table; 
     provider = APR_ARRAY_IDX(providers, i, svn_auth_provider_object_t *); 

     /* Add it to the appropriate table in the auth_baton */ 
     table = apr_hash_get(ab->tables, 
          provider->vtable->cred_kind, APR_HASH_KEY_STRING); 
     if (! table) 
     { 
      table = apr_pcalloc(pool, sizeof(*table)); 
      table->providers 
      = apr_array_make(pool, 1, sizeof(svn_auth_provider_object_t *)); 

      apr_hash_set(ab->tables, 
         provider->vtable->cred_kind, APR_HASH_KEY_STRING, 
         table); 
     } 
     APR_ARRAY_PUSH(table->providers, svn_auth_provider_object_t *) 
     = provider; 
    } 

    *auth_baton = ab; 
} 

Ma meilleure estimation est que le segfault se passe dans APR_ARRAY_IDX. Tout le reste a une adresse mémoire valide.

Informations complémentaires: Cela ne fonctionne pas non plus:

providers = apr_array_make(pool, 1, svn_auth_provider_object_t.sizeof); 
svn_auth_provider_object_t* newSlot = cast(svn_auth_provider_object_t*) apr_array_push(providers); 
svn_auth_get_simple_provider2(&newSlot, null, null, pool); 
svn_auth_open(&auth_baton, providers, pool); 

Alors que les règles sur ma théorie que les données ne va au bon endroit. Cependant, si je commente la ligne de commande du tableau et envoie le tableau vide, cela fonctionne correctement. Donc, cela ne pas segmentation fault:

providers = apr_array_make(pool, 1, svn_auth_provider_object_t.sizeof); 
svn_auth_open(&auth_baton, providers, pool); 

Je sais aussi qu'il est svn_auth_get_simple_provider2 pas parce que ce segfaults et ...

providers = apr_array_make(pool, 1, svn_auth_provider_object_t.sizeof); 
svn_auth_provider_object_t* newSlot = cast(svn_auth_provider_object_t*) apr_array_push(providers); 
svn_auth_get_ssl_server_trust_file_provider(&newSlot, pool); 
svn_auth_open(&auth_baton, providers, pool); 
+0

De manière à ce que le contrôle segfault soit définitif, gdb version 7.2 devrait fonctionner avec D. Donc, si vous compilez avec '-gc' et que les dumps core sont activés, vous devriez être capable de voir ce qui cause le segfault en utilisant gdb. –

+0

Je suis novice dans l'écriture de programmes qui se résument au langage machine. Donc, je ne suis pas familier avec gdb, j'essaie de l'utiliser mais je ne m'attendais pas à ce qu'il fonctionne bien avec D. Tout ce que j'ai compris jusqu'ici est de faire marche arrière. –

+0

auto n'est pas un type. Cela permet d'inférer le type, puisque le compilateur sait quel type est renvoyé par la fonction. Le type ne peut pas être modifié, et vous pouvez trouver ce que c'est avec typeid (var). –

Répondre

3

À première vue, la première affectation à newSlot est mort comme la ligne suivante l'écrase, la définissant sur null. Essayez:

auto newSlot = cast(svn_auth_provider_object_t**)apr_array_push(m); 
*newSlot = provider; 

Cela aurait donné lieu à une erreur de compilation si elle n'a pas été void*.

Je pense que la seule partie de la version C qui n'est pas valide D est la distribution.

+0

Et cela a fonctionné! Même si j'ai laissé la variable 'm 'par erreur. Je vais faire d'autres recherches sur ce type 'auto '. Je l'ai déjà vu mais je vois qu'il serait utile de le comprendre complètement. Toute ressource que vous pourriez suggérer serait appréciée puisque la documentation de D semble éparse. –

+0

@Jacks_Depression: auto est juste un espace réservé (const ou immutable fonctionnerait aussi). La forme générale est que le type peut être omis d'une déclaration-et-initialisation et il est supposé être le type des choses qui lui sont assignées: http://digitalmars.com/d/2.0/declaration.html# AutoDéclaration – BCS