在Innodb中使用rec_get_offsets来获取一条rec_t的各个字段的偏移量
整个rec_get_offsets的形式为:
/******************************************************//** The following function determines the offsets to each field in the record. It can reuse a previously allocated array. @return the new offsets */ UNIV_INTERN ulint* rec_get_offsets_func( /*=================*/ const rec_t* rec, /*!< in: physical record */ const dict_index_t* index, /*!< in: record descriptor */ ulint* offsets,/*!< in/out: array consisting of offsets[0] allocated elements, or an array from rec_get_offsets(), or NULL */ ulint n_fields,/*!< in: maximum number of initialized fields (ULINT_UNDEFINED if all fields) */ mem_heap_t** heap, /*!< in/out: memory heap */ const char* file, /*!< in: file name where called */ ulint line); /*!< in: line number where called */ #define rec_get_offsets(rec,index,offsets,n,heap) rec_get_offsets_func(rec,index,offsets,n,heap,__FILE__,__LINE__)
参数解释:
rec对应的记录
index记录对应的索引
offsets用来保存偏移量结果的指针,可以是预分配好的,也可以是个NULL
n_fields能保存的最大的偏移量的字段数一般可以使用ULINT_UNDEFINED来表示,没限制.ULINT_UNDEFINED为((ulint)(-1))
heap内存堆.如果没有预先分配offsets,那么返回结果将在heap上申请内存,如果heap为NULL,那么会为heap也申请内存.注意.这个地方很容易引起内存泄露
看上对offsets和heap的使用要注意了,一个不当就是引起内存泄露
看一个标准用法:
ulint offsets_[REC_OFFS_NORMAL_SIZE]; ulint* offsets = offsets_; mem_heap_t* heap = NULL; row_cache_chain_t* chain = NULL; rec_offs_init(offsets_); //TODO Someting if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); } return;
第一个需要注意的就是rec_offs_init(offsets_);这句不能省,这个宏的目的是设置offset_的第一个数组单位的值为数值的大小,因为rec_get_offsets内部需要判断offset能不能放下所有的值,放不下的话需要向heap申请内存,怎么判断offset够不够用,就需要rec_offs_init(offsets_);来初始化大小
上面这个例子里面使用的heap是为NULL的,即外部不预先为heap申请内存,难么当offset不够用时,rec_get_offsets内部会主动在heap上申请内存了.这个时候有个注意点就是rec_get_offsets内只在heap上申请了内存并没有free,因为外面还要使用,那么不能漏的就是
if (UNIV_LIKELY_NULL(heap)) { mem_heap_free(heap); }
这一段了,一旦漏了,就很有可能出现内存泄露,而且这个泄露的触发条件还很苛刻,因为初始化的offsets_[REC_OFFS_NORMAL_SIZE]为100个,那么当你有超过96个字段的记录(因为内部要预留4个)时,就会向heap申请内存,这时没有free就会泄露了.