2010-11-16 1 views
1

Я пишу программу в D, которая использует svn, и я наткнулся на то, что не могу понять, как преобразовать в синтаксис D. Я сделал удар, но это не так.Добавить массив, используя apr_array_push в D

Пример того, что я пытаюсь сделать в 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); 

Насколько я знаю, этот код работает отлично. Я нашел несколько примеров, сделанных почти точно так же. Вот моя попытка скопировать это в 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); 

Это бросает Сегментация Fault на svn_auth_open. Мое лучшее предположение заключается в том, что содержимое провайдера не заканчивается указателем, хранящимся в newSlot. И я не знаю, почему это так.

Дополнительный код:

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

Мое предположение, что происходит выдаёт ошибку сегментации в APR_ARRAY_IDX. Все остальное имеет действительный адрес памяти.

Дополнительная информация: Это не работает либо:

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

Так что исключает мою теорию о том, что данные не собирается в нужном месте. Однако, если я прокомментирую строку push массива и просто отправлю массив пустым, он отлично работает. Таким образом, это не сегментации:

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

Я также знаю, что это не svn_auth_get_simple_provider2, потому что это, а также ошибки сегментации ...

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

В качестве способа определения пути segfault версия gdb 7.2 должна работать с D. Итак, если вы компилируете с помощью '-gc' и включаете основные дампы, то вы должны уметь видеть, что вызывает segfault, используя GDB. –

+0

Я новичок в написании программ, которые скомпилируются до машинного языка. Поэтому я не знаком с gdb, я пытаюсь использовать его, но он не ожидал, что он будет хорошо работать с D. Все, что я догадался сделать до сих пор, - это откат. –

+0

авто не тип. Он позволяет вывести тип, поскольку компилятор знает, какой тип возвращается из функции. Тип не может быть изменен, и вы можете узнать, что это такое с typeid (var). –

ответ

3

На первый взгляд, первое назначение на newSlot мертв, как следующая строка перезаписывает его, устанавливая его на null. Попробуйте:

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

Это привело бы к компиляции ошибки времени, если бы не было void*.

Я думаю, что единственная часть версии C, которая недействительна D, - это актерский состав.

+0

И это сработало! Несмотря на то, что я по ошибке оставил переменную 'm '. Я собираюсь еще немного изучить этот тип «auto». Я видел это раньше, но я вижу, что было бы полезно понять это полностью. Любые ресурсы, которые вы можете предложить, будут оценены с учетом того, что документация D выглядит скудной. –

+0

@Jacks_Depression: auto - это только владелец места (const или неизменяемый также будет работать). Общая форма заключается в том, что тип можно исключить из объявления-инициализации и предполагается, что он является типом назначаемых ему вещей: http://digitalmars.com/d/2.0/declaration.html# AutoDeclaration – BCS

Смежные вопросы