Blender V4.3
leak_detector.cc
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2020-2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
9#include <any>
10#include <cstdio> /* Needed for `printf` on WIN32/APPLE. */
11#include <cstdlib>
12#include <mutex>
13#include <vector>
14
15#include "MEM_guardedalloc.h"
16#include "mallocn_intern.hh"
17
20 "Freeing memory after the leak detector has run. This can happen when using "
21 "static variables in C++ that are defined outside of functions. To fix this "
22 "error, use the 'construct on first use' idiom.";
23
24namespace {
25
26bool fail_on_memleak = false;
27bool ignore_memleak = false;
28
29class MemLeakPrinter {
30 public:
31 ~MemLeakPrinter()
32 {
33 if (ignore_memleak) {
34 return;
35 }
37 const uint leaked_blocks = MEM_get_memory_blocks_in_use();
38 if (leaked_blocks == 0) {
39 return;
40 }
41 const size_t mem_in_use = MEM_get_memory_in_use();
42 printf("Error: Not freed memory blocks: %u, total unfreed memory %f MB\n",
43 leaked_blocks,
44 double(mem_in_use) / 1024 / 1024);
46
47 /* In guarded implementation, the fact that all allocated memory blocks are stored in the
48 * static `membase` listbase is enough for LSAN to not detect them as leaks. Clearing it solves
49 * that issue. */
51
52 if (fail_on_memleak) {
53 /* There are many other ways to change the exit code to failure here:
54 * - Make the destructor `noexcept(false)` and throw an exception.
55 * - Call exit(EXIT_FAILURE).
56 * - Call terminate().
57 */
58 abort();
59 }
60 }
61};
62} // namespace
63
65{
66 /* Calling this ensures that the memory usage counters outlive the memory leak detection. */
68
69 /* Ensure that the static memleak data storage is initialized before the #MemLeakPrinter one, so
70 * that it outlives the memory leak detection. */
71 std::any any_data = std::make_any<int>(0);
73
83 static MemLeakPrinter printer;
84}
85
86void MEM_use_memleak_detection(bool enabled)
87{
88 ignore_memleak = !enabled;
89}
90
92{
93 fail_on_memleak = true;
94}
95
97{
98 static std::mutex mutex;
99 static std::vector<std::any> data_vec;
100 std::lock_guard lock{mutex};
101 data_vec.push_back(std::move(data));
102}
unsigned int uint
ThreadMutex mutex
Read Guarded memory(de)allocation.
volatile int lock
#define printf
bool enabled
void MEM_use_memleak_detection(bool enabled)
void MEM_enable_fail_on_memleak()
bool leak_detector_has_run
void MEM_init_memleak_detection()
char free_after_leak_detection_message[]
size_t(* MEM_get_memory_in_use)(void)
Definition mallocn.cc:62
void(* mem_clearmemlist)(void)
Definition mallocn.cc:67
uint(* MEM_get_memory_blocks_in_use)(void)
Definition mallocn.cc:63
void(* MEM_printmemlist)(void)
Definition mallocn.cc:56
static size_t mem_in_use
void memory_usage_init(void)
void add_memleak_data(std::any data)