2009-11-30 2 views
4

Код ниже компилируется, но сразу же падает по причинам, очевидным для других, но не для меня. Кажется, я не понимаю, может ли кто-нибудь сказать мне, как это исправить.Malloc указатель на указатель на массив структур по ссылке

*array_ref[2] = array[0]; 
*array_ref[3] = array[1]; 

Он падает на этой части каждый раз.

typedef struct test { 
    char *name; 
    char *last_name; 
} person; 



int setName(person ** array, person ***array_ref) { 

    *array = malloc (5 * sizeof(person)); 
    *array_ref= malloc(5 * sizeof(person*)); 

    array[0]->name = strdup("Bob"); 
    array[1]->name = strdup("Joseph"); 
    array[0]->last_name = strdup("Robert"); 
    array[1]->last_name = strdup("Clark"); 


*array_ref[2] = array[0]; 
*array_ref[3] = array[1]; 


    return 1; 
} 



int main() 
{ 
    person *array; 
    person **array_r; 

    setName(&array,&array_r); 

    printf("First name is %s %s\n", array[0].name, array[0].last_name); 
    printf("Second name is %s %s\n", array_r[3]->name, array_r[3]->last_name); 

    while(1) {} 
    return 0; 
} 
+3

Что вы обычно должны делать в случае, когда ваш код имеет ошибку, особенно когда ошибка является фактическим сбоем и происходит каждый раз, заключается в попытке сузить ее до наименьшего количества кода, который все еще делает это. Это облегчит для других поиск ошибки при просмотре кода и, что более важно, намного проще ** вы ** понять, что именно вызывает крах. –

+0

@ Эдан, я бы не сказал, что это проблема в этом случае. Здесь не так много кода, и проблема довольно ясна. –

+0

+1 Edan. Сужение этого, чтобы удалить 'array_ref', проясняет проблему и, несомненно, поможет ZPS понять это. – 2009-11-30 00:39:50

ответ

6

Оператор [] имеет более высокий приоритет, чем унарный operator*. Следовательно, это:

*array_ref[2] = array[0]; 
*array_ref[3] = array[1]; 

на самом деле означает:

*(array_ref[2]) = array[0]; 
*(array_ref[3]) = array[1]; 

Типы правильны здесь, поэтому он компилирует. Но из вашего кода ясно, что ваше намерение на самом деле было:

(*array_ref)[2] = array[0]; 
(*array_ref)[3] = array[1]; 

Так что просто используйте круглые скобки.

+0

Помните, что 'array [1]' не выделен :). –

1

Вы выделили место для указателей array_ref, но не для того, на что они указывают.

+0

Он указывает на объекты, которые выделены, это не проблема. – 2009-11-30 00:33:58

1

Попробуйте изменить следующее SetName()

*array_ref[2] = array[0]; 
*array_ref[3] = array[1]; 

в

*(*array_ref+2) = array[0]; 
*(*array_ref+3) = array[1]; 

Это работает.

1

array[1]->name - ваша проблема. Это должно быть (*array)[1].name. Обратите внимание, что эти два не эквивалентны. Все аналогичные применения имеют одинаковую проблему, за исключением [0], что случайно делает правильную вещь.

Помните, что array, параметр функции, не ваш массив, это указатель на ваш массив.

1

В функциях, как это я предпочитаю такой код:

int setName(person ** out_array, person ***out_array_ref) { 
    person* array = malloc(5 * sizeof(person)); 
    person** array_ref = malloc(5 * sizeof(person*)); 
    array[0].name = strdup("Bob"); 
    array[1].name = strdup("Joseph"); 
    array[0].last_name = strdup("Robert"); 
    array[1].last_name = strdup("Clark"); 
    // I'm guessing this was your intent for array_ref, here: 
    array_ref[2] = &array[0]; 
    array_ref[3] = &array[1]; 

    *out_array = out_array; 
    *out_array_ref = array_ref; 
    return 1; 
} 

Обратите внимание, что это улавливает и array[1]->name как отметил Роджер Паштет и *array_ref[2] = array[0], как (почти) отмечает Павел - решение которого (* array_ref) [2 ] = array [0] назначает из нераспределенного person*array[1] - оба из которых трудно заметить с дополнительным разыменованием.

Конечно, я в основном делаю это, потому что я использую C++, и это повышает безопасность исключений;).

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