Skip to content

gtk.cfg: g_idle_add and g_timeout_add take the data pointer - #9008

Open
pduchi wants to merge 1 commit into
cppcheck-opensource:mainfrom
pduchi:gtk-cfg-glib-source-data-ownership
Open

pduchi wants to merge 1 commit into
cppcheck-opensource:mainfrom
pduchi:gtk-cfg-glib-source-data-ownership

Conversation

@pduchi

@pduchi pduchi commented Nov 9, 2026 •

Copy link
Copy Markdown
Contributor

I don't have a Trac account, so there is no ticket for this; the details are below. Feel free to create one and I'll add it to the title.

#include <glib.h>

static gboolean free_data(gpointer data)
{
    g_free(data);
    return FALSE;
}

void f(void)
{
    gchar *data = g_strdup("data");
    g_timeout_add(10, free_data, data);
}

$ cppcheck --library=gtk idle.c
idle.c:13:1: error: Memory leak: data [memleak]

GLib passes the data to the callback, and to the destroy notify of the _full variants, which commonly frees it, so there is no leak. gtk.cfg marked these functions <leak-ignore/>:

  • g_idle_add, g_idle_add_full
  • g_timeout_add, g_timeout_add_seconds, g_timeout_add_full, g_timeout_add_seconds_full

They are now <use> in the g_free memory group, without <leak-ignore/>. Their only pointer arguments are the callback, the data and the destroy notify, so <use> can't hide another leak.

This is the gtk.cfg change that #8953 (#15137) was made for: without that fix, --check-library still reported checkLibraryUseIgnore for these functions. Here <use> means what the reference describes: the function takes over the pointer.

Tests: test/cfg/gtk.c covers all six functions; the memleak false positives show without the change. cfg/gtk.cfg validates against cppcheck-cfg.rng.

The data given to g_idle_add(), g_timeout_add() and their _seconds/_full
variants is passed to the callback (and the destroy notify), which
usually frees it. With <leak-ignore/> every such call was reported as
  Memory leak: data
Configure them as <use> instead.

@dmcppcheck dmcppcheck left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI review

This PR causes a new false negative: leaks of a GMainContext passed to g_main_context_invoke / g_main_context_invoke_full are no longer reported. CheckLeakAutoVarImpl::functionCall applies a <use> function to every plain pointer variable in the call, because <use> has no argument number. So g_main_context_invoke(ctx, cb, NULL) now marks the context in ctx as taken over. That context comes from g_main_context_new(), which is in the g_main_context_unref group. GLib does not take ownership of the context; it only refs it internally. The base config reports Memory leak: ctx for this code; the PR does not. g_idle_add* and g_timeout_add* don't have this problem, because their only pointer parameters are the callback, the data and the destroy notify.

The memleak false positives that the PR is about are gone, and test/cfg/gtk.c passes. The new <arg> configuration for g_main_context_invoke* works: it reports a NULL callback as nullPointer and an uninitialized callback or priority as uninitvar.

Testing

Build: make -j8 cppcheck testrunner in pr/ succeeded.

cfg test: I ran test/cfg/gtk.c with the runtests.sh options (--check-library --platform=unix64 --enable=style,information --inconclusive --force --check-level=exhaustive --inline-suppr ... --library=gtk).

  • With the PR's gtk.cfg: clean, exit code 0.
  • With the base gtk.cfg: 8 memleak errors in the new test functions. So the test does cover the change.

Regression found (I compared the PR's cfg with a copy of base's gtk.cfg, both run with the PR binary, since only the cfg changed):

static gboolean cb(gpointer data) { g_free(data); return FALSE; }
void ctx_leak(void)
{
    GMainContext *ctx = g_main_context_new();
    g_main_context_invoke(ctx, cb, NULL);
}
void ctx_ok(void)
{
    GMainContext *ctx = g_main_context_new();
    g_main_context_invoke(ctx, cb, NULL);
    g_main_context_unref(ctx);
}
$ cppcheck -q --library=/tmp/b/gtkbase.cfg t2.c
t2.c:16:1: error: Memory leak: ctx [memleak]
$ cppcheck -q --library=pr/cfg/gtk.cfg t2.c
(no output)

g_main_context_invoke_full(ctx, 0, cb, NULL, NULL) behaves the same way: base reports the leak, the PR does not.

Other checks:

  • g_main_context_invoke(NULL, NULL, NULL) now gives nullPointer, and an uninitialized callback or priority gives uninitvar.
  • A malloc'd or g_new'd pointer passed as the data is no longer reported, and no mismatch is reported either.
  • A conditional if (x) g_idle_add(cb, p); is no longer reported. That matches how if (x) g_free(p); is already handled, so I don't count it as a problem of this PR.

Automated review of 51b97a0 by Claude. The pull request was built and tested locally.

Comment thread cfg/gtk.cfg Outdated
<use>g_register_data</use>
<use>g_idle_add</use>
<use>g_idle_add_full</use>
<use>g_main_context_invoke</use>

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AI review

<use> has no argument number. CheckLeakAutoVarImpl::functionCall treats every plain pointer variable in a non-leak-ignore call as taken over, and that includes the GMainContext *context argument. As a result, this leak is no longer found (base reports Memory leak: ctx, the PR reports nothing):

void f(void) {
    GMainContext *ctx = g_main_context_new();
    g_main_context_invoke(ctx, cb, NULL);
}

The same happens with g_main_context_invoke_full. GLib does not take ownership of the context. Consider adding a test/cfg/gtk.c case with // cppcheck-suppress memleak for this, and fixing it in the library or check, for example with a per-argument <use>/ownership setting. Otherwise, consider leaving the g_main_context_invoke* functions out of this change.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks, you're right: applies to every pointer argument, so g_main_context_invoke(ctx, ...) hid a leak of ctx. I dropped g_main_context_invoke and g_main_context_invoke_full from this PR; they keep for now.

@pduchi
pduchi force-pushed the gtk-cfg-glib-source-data-ownership branch from 51b97a0 to 46f1427 Compare November 10, 2026 10:06
@pduchi pduchi changed the title gtk.cfg: g_idle_add, g_timeout_add and g_main_context_invoke take the data pointer gtk.cfg: g_idle_add and g_timeout_add take the data pointer Nov 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants