In git (option parsing and some other places), we sometimes leak tiny bits of memory on purpose. Introduce a way to declare such allocations, to make the lives of people searching for real memory leaks easier. Currently these are thin wrappers around xmalloc and xstrdup. The KEEP_WRAPPER attribute avoids a tail call to ensure their stack frame does not get replaced with the true xmalloc/xstrdup, so tools like valgrind can easily distinguish them and know that the memory they return is not meant to be freed. In the long run it might be nice to tighten the semantics of these functions and use memory from a large pool that is never freed (to avoid fragmentation and save some allocation overhead). Signed-off-by: Jonathan Nieder <jrnieder@xxxxxxxxx> --- cache.h | 2 ++ git-compat-util.h | 2 ++ path.c | 10 ++++++++++ t/valgrind/default.supp | 17 +++++++++++++++++ wrapper.c | 14 ++++++++++++++ 5 files changed, 45 insertions(+), 0 deletions(-) diff --git a/cache.h b/cache.h index 9ee61a2..bbf32ff 100644 --- a/cache.h +++ b/cache.h @@ -638,6 +638,8 @@ extern char *git_snpath(char *buf, size_t n, const char *fmt, ...) __attribute__((format (printf, 3, 4))); extern char *git_pathdup(const char *fmt, ...) __attribute__((format (printf, 1, 2))); +extern char *git_pathdup_permanent(const char *fmt, ...) + __attribute__((format (printf, 1, 2))); /* Return a statically allocated filename matching the sha1 signature */ extern char *mkpath(const char *fmt, ...) __attribute__((format (printf, 1, 2))); diff --git a/git-compat-util.h b/git-compat-util.h index 81883e7..f00ee33 100644 --- a/git-compat-util.h +++ b/git-compat-util.h @@ -380,7 +380,9 @@ typedef void (*try_to_free_t)(size_t); extern try_to_free_t set_try_to_free_routine(try_to_free_t); extern char *xstrdup(const char *str); +extern char *strdup_permanent(const char *str); extern void *xmalloc(size_t size); +extern void *alloc_permanent(size_t size); extern void *xmallocz(size_t size); extern void *xmemdupz(const void *data, size_t len); extern char *xstrndup(const char *str, size_t len); diff --git a/path.c b/path.c index a2c9d1e..332c903 100644 --- a/path.c +++ b/path.c @@ -87,6 +87,16 @@ char *git_pathdup(const char *fmt, ...) return xstrdup(path); } +char *git_pathdup_permanent(const char *fmt, ...) +{ + char path[PATH_MAX]; + va_list args; + va_start(args, fmt); + (void)git_vsnpath(path, sizeof(path), fmt, args); + va_end(args); + return strdup_permanent(path); +} + char *mkpath(const char *fmt, ...) { va_list args; diff --git a/t/valgrind/default.supp b/t/valgrind/default.supp index 7789edd..d237210 100644 --- a/t/valgrind/default.supp +++ b/t/valgrind/default.supp @@ -45,6 +45,23 @@ } { + leaky malloc for option parsing and configuration + Memcheck:Leak + fun:malloc + fun:xmalloc + fun:alloc_permanent +} + +{ + leaky strdup for option parsing and configuration + Memcheck:Leak + fun:malloc + fun:strdup + fun:xstrdup + fun:strdup_permanent +} + +{ see api-lockfile.txt Memcheck:Leak fun:calloc diff --git a/wrapper.c b/wrapper.c index fd8ead3..88ca3dd 100644 --- a/wrapper.c +++ b/wrapper.c @@ -3,6 +3,8 @@ */ #include "cache.h" +#define KEEP_WRAPPER __attribute__((optimize("-fno-optimize-sibling-calls"))) + static void try_to_free_builtin(size_t size) { release_pack_memory(size, -1); @@ -17,6 +19,12 @@ try_to_free_t set_try_to_free_routine(try_to_free_t routine) return old; } +KEEP_WRAPPER +char *strdup_permanent(const char *str) +{ + return xstrdup(str); +} + char *xstrdup(const char *str) { char *ret = strdup(str); @@ -29,6 +37,12 @@ char *xstrdup(const char *str) return ret; } +KEEP_WRAPPER +void *alloc_permanent(size_t size) +{ + return xmalloc(size); +} + void *xmalloc(size_t size) { void *ret = malloc(size); -- 1.7.2.3 -- To unsubscribe from this list: send the line "unsubscribe git" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html