數組的結構體定義:
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作者這麼計較內存爲什麼會有這種問題呢,真心不理解,感覺很容易解決啊。不過肯定有理由把,我們在使用的時候最好提前規劃好數組的大小,避免多次擴容造成的浪費。