mirror of
https://github.com/postgres/postgres.git
synced 2026-01-27 21:43:08 +03:00
When determining whether an allocated chunk is still reachable, Valgrind will consider only pointers within what it believes to be allocated chunks. Normally, all of a block obtained from malloc() would be considered "allocated" --- but it turns out that if we use VALGRIND_MEMPOOL_ALLOC to designate sub-section(s) of a malloc'ed block as allocated, all the rest of that malloc'ed block is ignored. This leads to lots of false positives of course. In particular, in any multi-malloc-block context, all but the primary block were reported as leaked. We also had a problem with context "ident" strings, which were reported as leaked unless there was some other pointer to them besides the one in the context header. To fix, we need to use VALGRIND_MEMPOOL_ALLOC to designate a context's management structs (the context struct itself and any per-block headers) as allocated chunks. That forces moving the VALGRIND_CREATE_MEMPOOL/VALGRIND_DESTROY_MEMPOOL calls into the per-context-type code, so that the pool identifier can be made as soon as we've allocated the initial block, but otherwise it's fairly straightforward. Note that in Valgrind's eyes there is no distinction between these allocations and the allocations that the mmgr modules hand out to user code. That's fine for now, but perhaps someday we'll want to do better yet. When reading this patch, it's helpful to start with the comments added at the head of mcxt.c. Author: Andres Freund <andres@anarazel.de> Co-authored-by: Tom Lane <tgl@sss.pgh.pa.us> Discussion: https://postgr.es/m/285483.1746756246@sss.pgh.pa.us Discussion: https://postgr.es/m/20210317181531.7oggpqevzz6bka3g@alap3.anarazel.de
84 lines
2.2 KiB
C
84 lines
2.2 KiB
C
/*-------------------------------------------------------------------------
|
|
*
|
|
* memdebug.h
|
|
* Memory debugging support.
|
|
*
|
|
* Currently, this file either wraps <valgrind/memcheck.h> or substitutes
|
|
* empty definitions for Valgrind client request macros we use.
|
|
*
|
|
*
|
|
* Portions Copyright (c) 1996-2025, PostgreSQL Global Development Group
|
|
* Portions Copyright (c) 1994, Regents of the University of California
|
|
*
|
|
* src/include/utils/memdebug.h
|
|
*
|
|
*-------------------------------------------------------------------------
|
|
*/
|
|
#ifndef MEMDEBUG_H
|
|
#define MEMDEBUG_H
|
|
|
|
#ifdef USE_VALGRIND
|
|
#include <valgrind/memcheck.h>
|
|
#else
|
|
#define VALGRIND_CHECK_MEM_IS_DEFINED(addr, size) do {} while (0)
|
|
#define VALGRIND_CREATE_MEMPOOL(context, redzones, zeroed) do {} while (0)
|
|
#define VALGRIND_DESTROY_MEMPOOL(context) do {} while (0)
|
|
#define VALGRIND_MAKE_MEM_DEFINED(addr, size) do {} while (0)
|
|
#define VALGRIND_MAKE_MEM_NOACCESS(addr, size) do {} while (0)
|
|
#define VALGRIND_MAKE_MEM_UNDEFINED(addr, size) do {} while (0)
|
|
#define VALGRIND_MEMPOOL_ALLOC(context, addr, size) do {} while (0)
|
|
#define VALGRIND_MEMPOOL_FREE(context, addr) do {} while (0)
|
|
#define VALGRIND_MEMPOOL_CHANGE(context, optr, nptr, size) do {} while (0)
|
|
#define VALGRIND_MEMPOOL_TRIM(context, addr, size) do {} while (0)
|
|
#endif
|
|
|
|
|
|
#ifdef CLOBBER_FREED_MEMORY
|
|
|
|
/* Wipe freed memory for debugging purposes */
|
|
static inline void
|
|
wipe_mem(void *ptr, size_t size)
|
|
{
|
|
VALGRIND_MAKE_MEM_UNDEFINED(ptr, size);
|
|
memset(ptr, 0x7F, size);
|
|
VALGRIND_MAKE_MEM_NOACCESS(ptr, size);
|
|
}
|
|
|
|
#endif /* CLOBBER_FREED_MEMORY */
|
|
|
|
#ifdef MEMORY_CONTEXT_CHECKING
|
|
|
|
static inline void
|
|
set_sentinel(void *base, Size offset)
|
|
{
|
|
char *ptr = (char *) base + offset;
|
|
|
|
VALGRIND_MAKE_MEM_UNDEFINED(ptr, 1);
|
|
*ptr = 0x7E;
|
|
VALGRIND_MAKE_MEM_NOACCESS(ptr, 1);
|
|
}
|
|
|
|
static inline bool
|
|
sentinel_ok(const void *base, Size offset)
|
|
{
|
|
const char *ptr = (const char *) base + offset;
|
|
bool ret;
|
|
|
|
VALGRIND_MAKE_MEM_DEFINED(ptr, 1);
|
|
ret = *ptr == 0x7E;
|
|
VALGRIND_MAKE_MEM_NOACCESS(ptr, 1);
|
|
|
|
return ret;
|
|
}
|
|
|
|
#endif /* MEMORY_CONTEXT_CHECKING */
|
|
|
|
#ifdef RANDOMIZE_ALLOCATED_MEMORY
|
|
|
|
void randomize_mem(char *ptr, size_t size);
|
|
|
|
#endif /* RANDOMIZE_ALLOCATED_MEMORY */
|
|
|
|
|
|
#endif /* MEMDEBUG_H */
|