klib 的项目地址:https://github.com/attractivechaos/klib/
klib 官方文档:http://attractivechaos.github.io/klib/
总的来说整个 klib 库小巧且功能强大,各种实现之间没有依赖,大多只需要 include 头文件即可使用,目前已经使用过的有 khash 和 klist,这里先说我个人在使用 khash 的过程中遇到的问题和使用过程中需要注意的点。
上面的 klib 官方文档链接中有不少入门的小例子,但也只是简单的使用方法,很多接口并没有提及,不过也有可能作者没有及时更新文档中的例子。
在使用过程中要时刻谨记 khash 中给出的接口都是宏,这也意味着在调试的时候很不方便,如果搞不懂一个接口的意思或者想知道这个接口都做了什么,最好还是看一下 khash.h 中的实现。
就我个人来说,最想提出要注意的一点是 内存释放
,在过去一段时间内,我手上依赖 klib 的程序一直都有内存泄漏,不过我始终没有找到原因,直到昨天我才终于定位到是 khash 相关的数据没有被彻底释放。导致这一问题出现的重要原因也在于我接手这个项目时,khash 相关的释放代码已经大量存在了,以至于先入为主,令我以为正确的释放操作就应该就那样,昨天定位到这个问题后我仔细分析了一下 khash 的源码,发现一直以来程序里关于销毁释放内存的操作,一直都是错误的。下面只会使用正确的方法(至少目前我认为是正确的:)),以免误导了其他人。
khash 里面提供了两种数据结构:hashmap 和 hashset,两种结构的使用方法大致是一样的,可以把 hashset 结构看作是没有值的 hashmap。
demo1 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 KHASH_MAP_INIT_INT(MAP_int2int, int ); khash_t (MAP_int2int) *map_int2int = kh_init(MAP_int2int); khiter_t iter = 0 ; iter = kh_get(MAP_int2int, map_int2int, 100 ); if (iter == kh_end(map_int2int)) { int ret = 0 ; iter = kh_put(MAP_int2int, map_int2int, 100 , &ret); } kh_value(map_int2int, iter) = 200 ; for (iter = kh_begin(map_int2int); iter != kh_end(map_int2int); iter++) { if (!kh_exist(map_int2int, iter)) { continue ; } do_something_foo(kh_key(map_int2int, iter)); do_something_bar(kh_val(map_int2int, iter)); } kh_del(MAP_int2int, map_int2int, iter); kh_clear(MAP_int2int, map_int2int); do_something_zzz(map_int2int); kh_destroy(MAP_int2int, map_int2int);
demo2 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 struct { } struct_a_t struct_a_t *create_struct_a () { } void free_struct_a (struct_a_t *) { } void free_str (const char *c_str) { free (c_str); } char *test_key = "test_key_data" ;struct_a_t *test_value = create_struct_a();KHASH_MAP_INIT_STR(MAP_str2struct_p, struct_a_t *); khash_t (MAP_str2struct_p) *map_str2struct_p = kh_init(MAP_str2struct_p);khiter_t iter = 0 ;iter = kh_get(MAP_str2struct_p, map_str2struct_p, test_key); if (iter == kh_end(map_str2struct_p)) { int ret = 0 ; iter = kh_put(MAP_str2struct_p, map_str2struct_p, test_key, &ret); } kh_value(map_str2struct_p, iter) = test_value; for (iter = kh_begin(map_str2struct_p); iter != kh_end(map_str2struct_p); iter++) { if (!kh_exist(map_str2struct_p, iter)) { continue ; } do_something_foo(kh_key(map_str2struct_p, iter)); do_something_bar(kh_val(map_str2struct_p, iter)); } kh_del(MAP_str2struct_p, map_str2struct_p, iter); kh_clear(MAP_str2struct_p, map_str2struct_p); kh_free_vals(MAP_str2struct_p, map_str2struct_p, free_struct_a); kh_free(MAP_str2struct_p, map_str2struct_p, free_str); kh_destroy(MAP_str2struct_p, map_str2struct_p);
demo3 1 2 3 4 5 6 7 8 9 10 KHASH_MAP_INIT_INT(MAP_int2int, int ); KHASH_MAP_INIT_STR(MAP_str2map_p, khash_t (MAP_int2int) *); khash_t (MAP_str2map_p) *map_str2map_p = kh_init(MAP_str2map_p);