xcb 内存管理:我应该释放迭代器中的数据字段吗?
xcb memory management: Should I free data field in iterator?
xcb 中的某个列表 属性 上有一组用于迭代的函数。它们都以 iterator
结尾。例如,xcb_setup_roots_iterator
。并且有相应的以next
或其他结尾的函数进行迭代。
问题来了:
当我不再需要数据时,是否应该在迭代器的 data
字段上调用 free
?
这是一个示例。
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
的 return 值。
其他地方呢? 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
成员指向刚好超出最后一个屏幕末尾的位置。
换句话说:所有屏幕在内存中都紧随其后,在一个大的分配中。
I should always free the return value of xcb_wait_for_event. What about other places? What's the general principle of memory management in xcb?
xcb 并不真正进行任何解析。相反,它将 on-the-wire 协议描述为 C struct
s 并提供了一些使用这些协议的便捷方法。这意味着从连接中读取单个 X11“数据包”并将其放入一个大内存区域。其他一切都只是进入各个领域的指针魔法。
既然你问的是xcb_screen_t
:这是xcb_setup_t
的一部分。连接到 X11 服务器时,收到单个 xcb_setup_t
。这是放在一个大的分配中,您可以使用 xcb_get_setup
访问它。此内存由 libxcb 拥有并由 xcb_disconnect()
.
释放
“数据包”还有什么?好吧,每个回复、事件和错误都是一个数据包。因此,您必须释放从 xcb_wait_for_event()
获得的任何东西,而且还必须释放 xcb_*_reply()
。没有其他需要释放。
xcb 中的某个列表 属性 上有一组用于迭代的函数。它们都以 iterator
结尾。例如,xcb_setup_roots_iterator
。并且有相应的以next
或其他结尾的函数进行迭代。
问题来了:
当我不再需要数据时,是否应该在迭代器的 data
字段上调用 free
?
这是一个示例。
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
的 return 值。
其他地方呢? 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
成员指向刚好超出最后一个屏幕末尾的位置。
换句话说:所有屏幕在内存中都紧随其后,在一个大的分配中。
I should always free the return value of xcb_wait_for_event. What about other places? What's the general principle of memory management in xcb?
xcb 并不真正进行任何解析。相反,它将 on-the-wire 协议描述为 C struct
s 并提供了一些使用这些协议的便捷方法。这意味着从连接中读取单个 X11“数据包”并将其放入一个大内存区域。其他一切都只是进入各个领域的指针魔法。
既然你问的是xcb_screen_t
:这是xcb_setup_t
的一部分。连接到 X11 服务器时,收到单个 xcb_setup_t
。这是放在一个大的分配中,您可以使用 xcb_get_setup
访问它。此内存由 libxcb 拥有并由 xcb_disconnect()
.
“数据包”还有什么?好吧,每个回复、事件和错误都是一个数据包。因此,您必须释放从 xcb_wait_for_event()
获得的任何东西,而且还必须释放 xcb_*_reply()
。没有其他需要释放。