Just posting this for posterity, on something I used to track down memory leaks related to python closures. --- generator/Python.ml | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) diff --git a/generator/Python.ml b/generator/Python.ml index 4a96cf6..2ff17dd 100644 --- a/generator/Python.ml +++ b/generator/Python.ml @@ -578,9 +578,27 @@ let generate_python_methods_c () = pr " PyObject *buf; /* Optional pointer to persistent buffer. */\n"; pr "};\n"; pr "\n"; + pr "static size_t alloc_count;\n"; + pr "void\n"; + pr "dump_alloc_count (void)\n"; + pr "{\n"; + pr " char *cmd;\n"; + pr " if (!alloc_count) return;\n"; + pr " asprintf (&cmd, \"{ echo ' *** alloc_count:%%zu'; cat /proc/%%d/cmdline; } > /dev/tty\",\n"; + pr " alloc_count, getpid ());\n"; + pr " system (cmd);\n"; + pr " free (cmd);\n"; + pr "}\n"; + pr "\n"; pr "static struct user_data *\n"; pr "alloc_user_data (void)\n"; pr "{\n"; + pr " static bool init;\n"; + pr " if (!init) {\n"; + pr " init = true;\n"; + pr " atexit (dump_alloc_count);\n"; + pr " }\n"; + pr " alloc_count++;\n"; pr " struct user_data *data = calloc (1, sizeof *data);\n"; pr " if (data == NULL) {\n"; pr " PyErr_NoMemory ();\n"; @@ -594,6 +612,7 @@ let generate_python_methods_c () = pr "{\n"; pr " struct user_data *data = user_data;\n"; pr "\n"; + pr " alloc_count--;\n"; pr " if (data->fn != NULL)\n"; pr " Py_DECREF (data->fn);\n"; pr " if (data->buf != NULL)\n"; -- 2.28.0