簡體   English   中英

在C中檢查NULL指針不起作用

[英]Checking NULL Pointer In C Doesn't Work

我有一個函數可以返回多個間接指針,如下所示:

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

現在,當我想在main函數中檢索此結果時,它將顯示所有用戶名,但最后它將遇到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)

為什么while condition不能正常工作?

首先,

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

有一個問題-您想分配user_counts 指向 user實例,而不是user實例,因此該行應為

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

但是,有一種更簡便的方法sizeof運算符可以將表達式作為參數以及類型名稱。 因此,您可以將該行重寫為

a = malloc( sizeof *a * user_counts );

表達式 *a類型為user * ,因此sizeof *a等效於sizeof (user *) 這使您的工作變得更簡單,因為您不必弄清楚a指向的類型-使編譯器完成艱苦的工作。

您應該始終檢查malloc調用的結果。

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

其次重要的是,不要使用*(a+i)索引到a -用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 */
   }

現在,解決您的實際問題。 您的代碼由於以下原因之一而崩潰:

  • 最初malloca失敗了,所以你崩潰的使用第一線a[i] ;
  • a[i]之一的malloc失敗,因此您崩潰a[i]->id = 1
  • 你已經成功地分配內存的所有users_count的元素a - 沒有 a[i]NULL ,所以你過去循環的數組的最后一個元素,並嘗試取消引用緊隨其后的對象,這是最有可能不是一個有效的指針。

除了在每個malloc調用之后添加檢查之外,您還應該基於users_count循環:

for ( i = 0; i < users_count; i++ )
  printf("ID: %d \t %s\n", a[i]->id, a[i]->name);

或者,你需要分配一個額外的元素a並將其設置為NULL

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

注意, calloc將所有分配的內存初始化為0,因此您可以使用它,而不必擔心將元素顯式設置為NULL

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM