git/list[1] front-page[2] threads[3] people[4] search[5] about
 

[PATCH] git-compat-util.h: introduce CALLOC(x)

From
Taylor Blau <me@ttaylorr.com>
Date
Dec 5, 2022, 18:54 UTC
Message-ID
<6694c52b38674859eb0390c7f62da1209a8d8ec3.1670266373.git.me@ttaylorr.com>

When zero-initializing a struct without the use of static initializers like "{ 0 }", it is common to write one of:

    T *ptr = xcalloc(1, sizeof(T));
    T *ptr = xcalloc(1, sizeof(*ptr));

These correctly initialize "*ptr" to the all-zeros value, but have a couple of drawbacks. Notably, both initializations are verbose, but the former is a foot-gun. If "*ptr"'s type changes to something other than "T", the programmer has to remember to update not only the type of the variable, but the right-hand side of its initialization, too.

In git.git, it is sometimes common to write something like:
    T *ptr;
    CALLOC_ARRAY(ptr, 1);

...but that is confusing, since we're not initializing an array. Rather, we're using the CALLOC_ARRAY() macro to pretend like we are. But since the array length is 1, the effect is zero initializing a single element.

Introduce a new variant, CALLOC(x), which initializes "x" to the all-zeros value, without exposing the confusing use of CALLOC_ARRAY(), or the foot-guns available when using xcalloc() directly.

Write a Coccinelle patch which codifies these rules, but mark it as "pending" since the resulting diff is too large to include in a single patch:

    $ git apply .build/contrib/coccinelle/xcalloc.pending.cocci.patch
    $ git diff --shortstat
     89 files changed, 221 insertions(+), 178 deletions(-)
Signed-off-by: Taylor Blau <me@ttaylorr.com>
---
This is a follow-up on [1], where introducing CALLOC(x) as the preferred
alternative to CALLOC_ARRAY(x, 1) was first suggested.

The patch is straightforward, and I am pretty sure that the Coccinelle rules are right, too ;-). But as a first-time Coccinelle user, any extra scrutiny on those bits would be appreciated.

The main point of discussion I think is whether we should consider adopting this rule. I am biased, of course, but I think that we should.

In any case, we should focus our efforts on polishing v2.39.0, but I wanted to send this out to the list before I forgot about it.

[1]: https://lore.kernel.org/git/Y1MrXoobkVKngYL1@coredump.intra.peff.net/
 contrib/coccinelle/xcalloc.pending.cocci | 21 +++++++++++++++++++++
 git-compat-util.h                        |  8 ++++++++
 2 files changed, 29 insertions(+)
 create mode 100644 contrib/coccinelle/xcalloc.pending.cocci
diff --git a/contrib/coccinelle/xcalloc.pending.cocci b/contrib/coccinelle/xcalloc.pending.cocci
new file mode 100644
index 0000000000..83e4ca1a68
--- /dev/null
+++ b/contrib/coccinelle/xcalloc.pending.cocci
@@ -0,0 +1,21 @@
+@@
+type T;
+T *ptr;
+@@
+- ptr = xcalloc(1, \( sizeof(T) \| sizeof(*ptr) \) )
++ CALLOC(ptr)
+
+@@
+type T;
+identifier ptr;
+@@
+- T ptr = xcalloc(1, \( sizeof(T) \| sizeof(*ptr) \) );
++ T ptr;
++ CALLOC(ptr);
+
+@@
+type T;
+T *ptr;
+@@
+- CALLOC_ARRAY(ptr, 1)
++ CALLOC(ptr)
diff --git a/git-compat-util.h b/git-compat-util.h
index a76d0526f7..827e5be89c 100644
--- a/git-compat-util.h
+++ b/git-compat-util.h
@@ -1107,6 +1107,14 @@ static inline void move_array(void *dst, const void *src, size_t n, size_t size)
 		memmove(dst, src, st_mult(size, n));
 }

+/*
+ * Like CALLOC_ARRAY, but the argument is treated as a pointer to a
+ * single struct.
+ *
+ * Preferable over xcalloc(1, sizeof(...)), or CALLOC_ARRAY(..., 1).
+ */
+#define CALLOC(x) (x) = CALLOC_ARRAY((x), 1)
+
 /*
  * These functions help you allocate structs with flex arrays, and copy
  * the data directly into the array. For example, if you had:
--
2.38.0.16.g393fd4c6db
Next: René Scharfe
Message 1 of 21 in “git-compat-util.h: introduce CALLOC(x)”
  1. git-compat-util.h: introduce CALLOC(x)Taylor Blau, Dec 5, 2022
  2. René ScharfeDec 5, 2022
  3. Taylor BlauDec 5, 2022
  4. Ævar Arnfjörð BjarmasonDec 5, 2022
  5. Jeff KingDec 6, 2022
  6. Ævar Arnfjörð BjarmasonDec 6, 2022
  7. Jeff KingDec 7, 2022
  8. Taylor BlauDec 7, 2022
  9. Taylor BlauDec 7, 2022
  10. Ævar Arnfjörð BjarmasonDec 7, 2022
  11. Jeff KingDec 6, 2022
  12. Taylor BlauDec 7, 2022
  13. Ævar Arnfjörð BjarmasonDec 7, 2022
  14. Junio C HamanoDec 5, 2022
  15. Taylor BlauDec 6, 2022
  16. Jeff KingDec 6, 2022
  17. Junio C HamanoDec 6, 2022
  18. Taylor BlauDec 7, 2022
  19. Jeff KingDec 7, 2022
  20. Ævar Arnfjörð BjarmasonDec 6, 2022
  21. Jeff KingDec 7, 2022

Read the whole thread, see it on lore, or plain text.

$ cat FOOTERMessages come from the public archive at lore.kernel.org/git, fetched every hour. The front page is chosen and written each morning by an AI editor and can be wrong; the threads themselves are the record. About and API. For agents: an MCP server at https://gitlist.dev/mcp, and any thread, story or person page as Markdown by adding .md to its URL (or sending Accept: text/markdown). Details in /llms.txt.