2015-01-15 5 views
0

Я относительно новичок в программировании в целом, и я пытаюсь написать код для работы с квадратными матрицами. К сожалению, я застрял в самом начале развития, как кодОсновная проблема с C двойными указателями (матрицами)

typedef struct Matrix_t{ 
    float** content; 
    size_t size; 
} Matrix_t; 

int main(int argc, char** argv) { 
    Matrix_t* matr; 

    initMatrix(matr,s); 
    /* 
    ... 
    ... 
    ... 
    */ 
    return 0; 
} 

void initMatrix(Matrix_t* m, size_t s) { 
    int i; 

    m = (Matrix_t*) malloc(sizeof(Matrix_t)); 
    m->content = (float**) malloc(s*sizeof(float*)); 
    for(i=0;i<s;i++){ 
     m->content[i] = (float*) malloc(s*sizeof(float)); 
    } 

    m->size = s; 
} 

бы SIGSEGV сразу после initMatrix() делается. Используя отладчик, я узнал, что в основном вся информация о матрице теряется после закрытия initMatrix(). Почему это? И как я могу это исправить?

Заранее спасибо.

+1

'т = ...' если вы подумайте, что это повлияет на указатель, переданный из 'main()', вы можете пересмотреть это. Кроме того, я не вижу причин динамически выделять «Matrix_t» в первую очередь. Соответствующий * контент * уже управляется динамически. Что вы получаете, но еще несколько байтов в куче? – WhozCraig

+0

Переменная 'm' является локальной переменной в функции' initMatrix'. Все, что вы его установили, не имеет значения вне функции. По сути, выделенная память «потеряна» (a.k.a. * утечка памяти *) после завершения этой функции. –

+0

@barakmanos 'm' является локальным, но на самом деле это адрес переменной' matr'. Вы передаете указатель Матрицы на функцию, указатель функции указывает на выделенную память, после возврата 'initMatrix',' m' все равно должен быть выделен адрес памяти. Я ошибаюсь? Странно, что код не работает. Как вы думаете? –

ответ

1

В вашей функции вы изменяете только локальную автоматическую переменную m. C - это язык с переходом. Если вы хотите передать по адресу, то адрес - это то, что вам нужно передать, объявив формальный параметр как указатель к типу, , даже если этот тип уже является указателем, а то, что вы изменяете, является указателем сам.

Когда вы передаете что-то как в/из или из параметров, если вы оказываетесь это делаете:

void foo(Type *p) 
{ 
    p = malloc(...) 
} 

вы не модифицирующие данные указывают на по p, вы 'изменяет p сам, и вызывающий абонент не знает об изменениях. Адрес, сохраненный в p при входе, теряется. Где, как это:

void foo(Type *p) 
{ 
    *p = .... 
} 

модифицирует, что pуказывает на. Тем не менее, если Type уже указатель типа, а также то, что вы хотите изменить его в указатель сам, вы должны сделать это:

void foo(Type **pp) // declare a pointer-to-pointer-to-type 
{ 
    *pp = malloc(....) // dereference to store the address returned from malloc 
         // in the pointer pointed to by pp 
} 

Таким образом, самое непосредственное исправление объявить формальный параметр как указатель на указатель на тип, передавая адрес matr от main()

void initMatrix(Matrix_t **pp, size_t s) 
{ 
    int i; 

    Matrix_t *m = malloc(sizeof(Matrix_t)); 
    m->content = malloc(s*sizeof(float*)); 
    for(i=0;i<s;i++) 
     m->content[i] = malloc(s*sizeof(float)); 
    m->size = s; 
    *pp = m; // note: saving pointer to the output target 
} 


int main(int argc, char** argv) 
{ 
    Matrix_t* matr = NULL; 

    initMatrix(&matr,s); // note: passing address of pointer 

    /* 
    ... 
    ... 
    ... 
    */ 
    return 0; 
} 

Я ушел из проверки ошибок (или я должен сказать, что я не добавить любой, так как его не было, и удалили ненужные ролики с malloc, которые вы можете узнать больше о here.

Существует около полутора десятков способов сделать это, но это самый прямой вопрос о том, какой код у вас уже есть. Я бы посоветовал либо возвратить выделение из самой функции в качестве ret-val, либо даже не динамически распределять структуру, потому что нет необходимости делать это. Оба из них я оставляю для вас думать.

Удачи.

1

Make матри = NULL в основной функции и так, попробуйте:

main(){ 

    Matrix_t *matr=NULL; 
    /*Declare and initialize "s" variable.... */ 

    initMatrix(&matr,s); /* See below... */ 
    /* 
    ..... 
    */ 
} 

Используйте указатель на указатель в Matrix_t * м в функции initMatrix

void initMatrix(Matrix_t **m, size_t s) 
{  
    Matrix_t *aux=(Matrix_t*)malloc(sizeof(Matrix_t)); 

    /*check if matrix already allocated */ 
    if(*m != NULL) 
    {  
     /*Make a free matrix function to free the matrix before use*/   
     free_my_matrix(m); 
     *m=NULL; 
    } 

    /*** 
     Work with aux.... 
     aux->content=...malloc.... 
    ***/ 

    /* make your base pointer be aux */   
    *m=aux; 
}