nginx源碼初讀(5)--讓煩惱從數據結構開始(ngx_array)

數組的結構體定義:

typedef struct ngx_array_s       ngx_array_t;
struct ngx_array_s {
    void        *elts;           // 指向數組存儲位置的首地址
    ngx_uint_t   nelts;          // 當前數組中已經存放的元素個數
    size_t       size;           // 數組中每個元素的大小
    ngx_uint_t   nalloc;         // 當前最多能容納的元素個數,類似cpp中的Vector,當nelts大於nalloc時擴容
    ngx_pool_t  *pool;           // 該數組對應的內存池
};

下面介紹數組操作函數:

ngx_array_t *ngx_array_create(ngx_pool_t *p, ngx_uint_t n, size_t size);
/* 從pool中申請array結構體內存,並調用init初始化(申請n*size內存,改變array內的屬性),
 * 所以元素與結構體內存可能並不連續,但肯定在同一個pool裏,失敗返回NULL */

void ngx_array_destroy(ngx_array_t *a);
/* 依次銷燬數組的數據區和結構體內存,將內存返還給pool(last-=)
 * if ((u_char *) a + sizeof(ngx_array_t) == p->d.last) {
       p->d.last = (u_char *) a;
   }
 * 銷燬結構體的代碼如上,因爲這代碼看起來很奇怪,它怎麼知道數組肯定再pool的最後,沒加過其他東西了?
   看了源碼數組也並不是通過單獨的pool來管理的,也就是說pool中還可能有很多其他的數據。
   在nginx整個代碼中沒有找到對ngx_array_destroy的引用
 */

void *ngx_array_push(ngx_array_t *a);
void *ngx_array_push_n(ngx_array_t *a, ngx_uint_t n); 
/* 在數組a上新追加元素,並返回指向新元素的指針。需要把返回的指針轉換爲具體類型,
   然後再給新元素本身或者是各字段(如果數組的元素是複雜類型)賦值。*/

static ngx_inline ngx_int_t
ngx_array_init(ngx_array_t *array, ngx_pool_t *pool, ngx_uint_t n, size_t size)
/* 如果一個數組對象是被分配在堆上的,那麼當調用ngx_array_destroy銷燬以後,如果想再次使用,就可以調用此函數。
   如果一個數組對象是被分配在棧上的,那麼就需要調用此函數,進行初始化的工作以後,纔可以使用。*/

從以上代碼中大家有沒有發現一個很嚴肅的問題,不管是destroy還是擴容,源碼中原來的內存位置都是沒有free的,這樣肯定造成了內存的浪費,nginx作者這麼計較內存爲什麼會有這種問題呢,真心不理解,感覺很容易解決啊。不過肯定有理由把,我們在使用的時候最好提前規劃好數組的大小,避免多次擴容造成的浪費。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章