1. 程式人生 > >結構體指標內的指標變數成員的記憶體分配

結構體指標內的指標變數成員的記憶體分配

zclReportCmd_t *reportCmd;
typedef struct
{
  uint8       numAttr;       // number of reports in the list
  zclReport_t attrList[];    // attribute report list
} zclReportCmd_t;
typedef struct
{
  uint16 attrID;             // atrribute ID
  uint8  dataType;           // attribute data type
  uint8  *attrData;          // this structure is allocated, so the data is HERE
                             // - the size depends on the data type of attrID
} zclReport_t;

上述可知:

        reportCmd為一結構體指標!該結構體內的attrList成員也是一結構體,attrList結構體有attrData指標成員!

像上述這種指標結構體巢狀有指標的,或是但凡有指標的記憶體分配,都必須為每個指標變數單獨分配記憶體空間!

籠統的分配記憶體空間是錯誤的!

原因是:

       一般的記憶體分配都是連續性的分配塊記憶體的,指標變數存的是將要跳轉的空間地址,沒有把開闢的地址賦給巢狀在內層的指標變數!這樣跳轉到的地址並不一定就在剛分配開闢的連續地址內,只有將開闢的記憶體地址寫在指標變數裡,才能讓指標跳到指定的開闢的記憶體空間!

上例中錯誤的籠統分配就是

reportCmd = (zclReportCmd_t *)osal_msg_allocate(sizeof(zclReportCmd_t)+sizeof(zclReport_t)+ len);

把attrData指標要指向的空間和reportCmd指向的空間分在一塊了,開闢出的首地址賦給了reportCmd,reportCmd根據自己的值就可以正確的跳到開闢給自己的記憶體!但是沒有給attrData變數賦屬於他的開闢的地址,他根據自己原先隨機值跳就不一定跳到剛開闢的記憶體地址!

正確的做法:

reportCmd = (zclReportCmd_t *)osal_msg_allocate(sizeof(zclReportCmd_t)+sizeof(zclReport_t));//+ len);
reportCmd->attrList[0].attrData = (uint8*)osal_msg_allocate(len);

兩個指標就用兩次開闢記憶體!

reportCmd->attrList[0].attrData是report指標的成員,故它的記憶體地址是開闢reportCmd就開了,後面開的是它指向的地址,也就是len長的地址