Guarded allocator: Function to rename block for debugging

We have plenty of sorta generic functions, that allocate memory with
some generic name for debugging. When such a function is called and the
memory leaks, it may be unclear which call to it allocated the unfreed
memory (and thus which execution path leads to the leak).

The added function is only available if `NDEBUG` is not defined.

Differential Revision: https://developer.blender.org/D15605

Reviewed by: Sergey Sharybin, Bastien Montagne
This commit is contained in:
Julian Eisel 2022-08-04 11:12:15 +02:00
parent fdd282021a
commit 28e0cc424d
5 changed files with 32 additions and 0 deletions

View File

@ -199,6 +199,15 @@ extern size_t (*MEM_get_peak_memory)(void) ATTR_WARN_UNUSED_RESULT;
#ifndef NDEBUG
extern const char *(*MEM_name_ptr)(void *vmemh);
/**
* Change the debugging name/string assigned to the memory allocated at \a vmemh. Only affects the
* guarded allocator. The name must be a static string, because only a pointer to it is stored!
*
* Handy when debugging leaking memory allocated by some often called, generic function with a
* unspecific name. A caller with more info can set a more specific name, and see which call to the
* generic function allocates the leaking memory.
*/
extern void (*MEM_name_ptr_set)(void *vmemh, const char *str) ATTR_NONNULL();
#endif
/**

View File

@ -49,6 +49,7 @@ size_t (*MEM_get_peak_memory)(void) = MEM_lockfree_get_peak_memory;
#ifndef NDEBUG
const char *(*MEM_name_ptr)(void *vmemh) = MEM_lockfree_name_ptr;
void (*MEM_name_ptr_set)(void *vmemh, const char *str) = MEM_lockfree_name_ptr_set;
#endif
void *aligned_malloc(size_t size, size_t alignment)
@ -128,6 +129,7 @@ void MEM_use_lockfree_allocator(void)
#ifndef NDEBUG
MEM_name_ptr = MEM_lockfree_name_ptr;
MEM_name_ptr_set = MEM_lockfree_name_ptr_set;
#endif
}
@ -159,5 +161,6 @@ void MEM_use_guarded_allocator(void)
#ifndef NDEBUG
MEM_name_ptr = MEM_guarded_name_ptr;
MEM_name_ptr_set = MEM_guarded_name_ptr_set;
#endif
}

View File

@ -1199,4 +1199,18 @@ const char *MEM_guarded_name_ptr(void *vmemh)
return "MEM_guarded_name_ptr(NULL)";
}
void MEM_guarded_name_ptr_set(void *vmemh, const char *str)
{
if (!vmemh) {
return;
}
MemHead *memh = vmemh;
memh--;
memh->name = str;
if (memh->prev) {
MEMNEXT(memh->prev)->nextname = str;
}
}
#endif /* NDEBUG */

View File

@ -131,6 +131,7 @@ void MEM_lockfree_reset_peak_memory(void);
size_t MEM_lockfree_get_peak_memory(void) ATTR_WARN_UNUSED_RESULT;
#ifndef NDEBUG
const char *MEM_lockfree_name_ptr(void *vmemh);
void MEM_lockfree_name_ptr_set(void *vmemh, const char *str);
#endif
/* Prototypes for fully guarded allocator functions */
@ -174,6 +175,7 @@ void MEM_guarded_reset_peak_memory(void);
size_t MEM_guarded_get_peak_memory(void) ATTR_WARN_UNUSED_RESULT;
#ifndef NDEBUG
const char *MEM_guarded_name_ptr(void *vmemh);
void MEM_guarded_name_ptr_set(void *vmemh, const char *str);
#endif
#ifdef __cplusplus

View File

@ -426,4 +426,8 @@ const char *MEM_lockfree_name_ptr(void *vmemh)
return "MEM_lockfree_name_ptr(NULL)";
}
void MEM_lockfree_name_ptr_set(void *UNUSED(vmemh), const char *UNUSED(str))
{
}
#endif /* NDEBUG */