2

I'm writing some C code where I want to have a NULL-terminated GPtrArray containing static strings. Typically, I would use g_ptr_array_new_null_terminated () to construct a NULL-terminated GPtrArray, but it requires me to specify a function that frees the elements upon destruction—something you don't want with statically allocated strings, of course. However, I don't find any constructor that gives you a NULL-terminated array that doesn't require providing an element free function: both g_ptr_array_new_from_null_terminated_array () and g_ptr_array_new_take_null_terminated () require an element_free_func argument that cannot be set to NULL according to the documentation.

One option would of course be to just make a no-op function that fits the GDestroyNotify function signature, but it doesn't feel particularly elegant. Is there a better way of achieving this?

1
  • 1
    I think the no-op function is the intended solution. Elegance be damned! Commented yesterday

2 Answers 2

6

It's not documented, but it skips freeing when element_free_func is NULL. From the glib source code:

  if (rarray->element_free_func != NULL)
    {
      for (i = index_; i < index_ + length; i++)
        rarray->element_free_func (rarray->pdata[i]);
    }

But if you want to stick to documented features, I think the no-op function is the expected solution.

I think this is intended, so perhaps this should be considered a documentation bug and you could submit a bug report about it.

Sign up to request clarification or add additional context in comments.

5 Comments

I don't see any check for a NULL free function in this part of the code that allocates a new array: gitlab.gnome.org/GNOME/glib/-/blob/main/glib/garray.c#L1139
It doesn't check when creating, it checks when freeing.
The issue would be a check in the creation for a non-NULL free function causing the creation to fail.
Right. If it actively rejected this, it would be a problem. But it doesn't, it just saves whatever you provide in the element_free_func member variable, and uses it safely later.
element_free_func can be null. From Andrew's link, looking at (e.g.) the g_ptr_array_new_take function (amongst others), we have a comment: gitlab.gnome.org/GNOME/glib/-/blob/main/glib/garray.c#L1190 which is: @element_free_func: (nullable): a function to free elements on @array destruction Note the "(nullable)". Although this looks like a doxygen-like comment syntax, it doesn't (seem to) go to the docs pages, so it's "semi-documented" ;-)
4

I don't find any constructor that gives you a NULL-terminated array that doesn't require providing an element free function

Indeed, of the 8 (!) constructor functions in total for objects of this type, only g_ptr_array_new() does not take a pointer to a free function as an argument, and that function does not produce an array of the null-terminated flavor.

However, the docs do not specify the implications of providing a null pointer for the freeing function, and in practice, g_ptr_array_new() behaves as if you had passed such a null pointer. I don't necessarily think it's safe to rely on that, but it looks like you could get away with it for now. I would recommend documenting such an assumption if you make it.

One option would of course be to just make a no-op function that fits the GDestroyNotify function signature, but it doesn't feel particularly elegant.

I don't see why that seems inelegant to you. It seems natural to me.

Is there a better way of achieving this?

The way you propose seems fine to me, and it is the safest, most forward-looking option. However, if you can't bear to do that then it appears that using g_ptr_array_new_null_terminated() and passing NULL as the element freeing function probably would work too.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.