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 structs 并提供了一些使用这些协议的便捷方法。这意味着从连接中读取单个 X11“数据包”并将其放入一个大内存区域。其他一切都只是进入各个领域的指针魔法。

既然你问的是xcb_screen_t:这是xcb_setup_t的一部分。连接到 X11 服务器时,收到单个 xcb_setup_t。这是放在一个大的分配中,您可以使用 xcb_get_setup 访问它。此内存由 libxcb 拥有并由 xcb_disconnect().

释放

“数据包”还有什么?好吧,每个回复、事件和错误都是一个数据包。因此,您必须释放从 xcb_wait_for_event() 获得的任何东西,而且还必须释放 xcb_*_reply()。没有其他需要释放。