xcb memory management: Should I free data field in iterator?

465 Views Asked by At

There is a group of functions for iteration on some list property in xcb. They all end with iterator. For example, xcb_setup_roots_iterator. And there are corresponding functions ending with next or others for iteration.

Here comes the problem: Should I call free on the data field of iterator when I no longer need the data?

Here is a sample.

  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?*/

I know iter is on stack so it will be destroyed automatically. But what about data in it? In my thoughts xcb creates it and after using it I never pass it back to xcb so xcb has no chance to free it and I should manually free it to avoid memory leaks.

After searching the docs and web, I only find some limited info about memory management such as: 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?

1

There are 1 best solutions below

3
On BEST ANSWER

Short version: No, you should not free it.

Long version: Here is the implementation of 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;
}

As you see, this only does some pointer magic to compute the size of the screen and then incremenets the pointer by that amount, i.e. the new data member points just beyond the end of the last screen. Put differently: all screens are right behind each other in memory in a single, big allocation.

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 does not really do any parsing. Instead, it describes the on-the-wire protocol as C structs and provides some convenience methods for working with these. This means that a single X11 "packet" is read from the connection and put into one big memory region. Everything else is just pointer magic to get into the individual fields.

Since you are asking about xcb_screen_t: This is part of xcb_setup_t. When connecting to the X11 server, a single xcb_setup_t is received. This is put in one big allocation which you can access with xcb_get_setup. This memory is owned by libxcb and freed by xcb_disconnect().

What else are "packets"? Well, every reply, event, and error is a single packet. Thus, you have to free whatever you get from xcb_wait_for_event(), but also xcb_*_reply(). Nothing else needs to be freed.