问题描述
在xcb中的某些列表属性上有一组用于迭代的函数。它们都以iterator
结尾。例如,xcb_setup_roots_iterator
。并且有相应的函数以next
或其他函数结尾进行迭代。
问题来了:
当我不再需要数据时,应该在迭代器的free
字段上调用data
吗?
这里是一个样本。
int screen_num;
xcb_connection_t *connection = xcb_connect(NULL,&screen_num);
const xcb_setup_t *setup = xcb_get_setup(connection);
xcb_screen_iterator_t iter = xcb_setup_roots_iterator(setup);
for (; iter.rem; xcb_screen_next(&iter)) {
xcb_screen_t *screen = iter.data;
/*do something with screen*/
}
/*should I free iter.data here?*/
我知道iter
在堆栈中,因此它将被自动销毁。但是其中的data
呢?按照我的想法,xcb会创建它,并且在使用它后我再也不会将其传递回xcb,因此xcb没有机会释放它,因此我应该手动释放它以避免内存泄漏。
在搜索文档和网络后,我仅找到有关内存管理的一些有限信息,例如:
我应该始终释放xcb_wait_for_event
的返回值。
那其他地方呢? xcb中的内存管理的一般原理是什么?
解决方法
简短版本:不,您不应该释放它。
长版:
这是xcb_screen_next
的实现:
void
xcb_screen_next (xcb_screen_iterator_t *i)
{
xcb_screen_t *R = i->data;
xcb_generic_iterator_t child;
child.data = (xcb_screen_t *)(((char *)R) + xcb_screen_sizeof(R));
i->index = (char *) child.data - (char *) i->data;
--i->rem;
i->data = (xcb_screen_t *) child.data;
}
如您所见,这只会起到一些指针魔术的作用,以计算屏幕的大小,然后将指针增加该数量,即新的data
成员指向刚好超出最后一个屏幕末尾的位置。
换句话说:内存中的所有屏幕都在单个内存中紧挨着。
我应该始终释放xcb_wait_for_event的返回值。那其他地方呢? xcb中的内存管理的一般原理是什么?
xcb确实不执行任何解析。相反,它将在线协议描述为C struct
,并提供了一些使用这些协议的便捷方法。这意味着将从连接中读取单个X11“数据包”并将其放入一个大内存区域。其他所有东西只是进入各个字段的指针魔术。
由于您正在询问xcb_screen_t
:这是xcb_setup_t
的一部分。连接到X11服务器时,会收到一个xcb_setup_t
。这是一个很大的分配,您可以使用xcb_get_setup
进行访问。此内存归libxcb所有,并由xcb_disconnect()
释放。
“包”还有什么?好吧,每个答复,事件和错误都是一个数据包。因此,您必须释放从xcb_wait_for_event()
得到的一切,而且还要释放xcb_*_reply()
。不需要释放其他任何东西。