2017-01-25 2 views
0

動作しない私はそうのような結果として、複数の間接ポインタを返す関数があります:私は、主な機能で、この結果にクロールするとき、私は、今CでNULLポインタをチェックする

typedef struct { 
    int id; 
    char *name; 
} user; 

user **myfn(int users_count) { 
    user **a; 
    a = malloc(sizeof(user) * user_counts); 
    for(int i = 0 ; i<user_counts ; i++) { 
     *(a+i) = malloc(sizeof(user)); 
     (*(a+i))->id = 1; 
     (*(a+i))->name = malloc(sizeof(char) * 25); 
     strncpy((*(a+i))->name, "Morteza", 25); // just for example 
    } 
    return a; 
} 

を、それすべてのユーザー名が表示されますが、最後にSegmentation faultエラーが発生します。

int main() { 
    user **a = myfn(10); 
    int i = 0; 
    while((*(a+i)) != NULL) { 
     printf("ID: %d \t %s\n", (*(a+i))->id, (*(a+i))->name); 
     i++; 
    } 
} 

結果:

ID: 1 Morteza 
ID: 2 Morteza 
... 
... 
ID: 10 Morteza 
Segmentation fault (core dumped) 

whileconditionは正常に動作しないのはなぜ?すべての

+2

'a = malloc(sizeof(user)* user_counts);は間違っています。 '* a'は' user'ではなく 'user *'です。 – melpomene

+1

'strncpy'を使わないでください。これまで – melpomene

+2

'*(a + i)'は通常 'a [i]'と書かれています。 – melpomene

答えて

2

まず、

a = malloc(sizeof(user) * user_counts); 

には問題があります - あなたは、ないuserのインスタンスは、その行が

a = malloc(sizeof(user *) * user_counts); 

しかしをする必要がありますのでuserポインタのuser_countsインスタンスを割り当てたいですこの周りには簡単な方法があります。sizeofオペレータは、の式を引数として取ることができます型名だけでなく、だから、そうsizeof *asizeof (user *)に相当し、user *を入力した

a = malloc(sizeof *a * user_counts); 

表現*aとしてその行を書き換えることができます。これはあなたの人生を少しシンプルにします。つまり、aが指摘しているタイプを困惑させる必要はありません。コンパイラが難しい作業をするようにします。

常にを呼び出してください。mallocコールの結果を確認してください。

a = malloc(sizeof *a * users_count); 
if (a) 
{ 
    // do stuff with a 
} 

すべての第二に、aへのインデックスへ*(a+i)を使用していない - 代わりにa[i]を使用しています。物事を少し読みやすくします。だから、

*(a+i) = malloc(sizeof(user)); 
    (*(a+i))->id = 1; 
    (*(a+i))->name = malloc(sizeof(char) * 25); 

は、あなたの実際の問題に、今

a[i] = malloc(sizeof *a[i]); 
    if (a[i]) 
    { 
    a[i]->id = 1; 
    a[i]->name = malloc(sizeof *a[i]->name * 25); 
    } 
    else 
    { 
    /* deal with memory allocation failure */ 
    } 

になります。あなたのコードは、次のいずれかの理由でクラッシュしている:

  • aの初期mallocが失敗したので、あなたはa[i]を使用して最初の行にクラッシュしています。
  • a[i]のいずれかのmallocが失敗したため、a[i]->id = 1にクラッシュしています。 最も可能性が高いされていない、あなたの配列の最後の要素の過去のループあなたはので、すぐに次のオブジェクトを逆参照しようなしa[i]NULLです - あなたは成功しaのすべてusers_count要素のためのメモリが割り当てられてきた
  • 有効なポインタ

    あなたがaのために1つの余分な要素を割り当て、NULLに設定する必要があります
    for (i = 0; i < users_count; i++) 
        printf("ID: %d \t %s\n", a[i]->id, a[i]->name); 
    

    または、::

    users_countに基づいて、各mallocコールの後に検査を追加して、あなたがすべきおそらくループに加えて

a = malloc(sizeof *a * (users_count + 1)); 
if (a) 
{ 
    a[users_count] = NULL; 
    for (i = 0; i < users_count; i++) 
    ... 
} 

callocは割り当てられたすべてのメモリを0に初期化するので、これを使用して明示的にe NULLに:

a = calloc(users_count + 1, sizeof *a); 
if (a) 
{ 
    for (i = 0; i < users_count; i++) 
    ... 
} 
+1

技術的には、すべてのビット0にポインタを設定する( 'calloc'のように)、ヌルポインタを生成することは保証されません。 – melpomene

+0

@melpomene参考になっていますか? * 6.3.2.3ポインタ*、パラグラフ3は、 "0の値を持つ整数定数式、または の' void * '型にキャストされた式は、* nullポインタ定数*と呼ばれます。ほとんどのプラットフォームでは、少なくとも実装依存の 'NULL'ポインタ値であると思います。 。 –

+1

@AndrewHenleこれはどのように適用されるのかわかりません。 'calloc(...)'は値0の整数定数式を含んでいません。 – melpomene

関連する問題