Blender V5.0
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
8
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;
27
28class MemLeakPrinter {
29 public:
30 ~MemLeakPrinter()
31 {
33 const uint leaked_blocks = MEM_get_memory_blocks_in_use();
34 if (leaked_blocks == 0) {
35 return;
36 }
37 const size_t mem_in_use = MEM_get_memory_in_use();
38 printf("Error: Not freed memory blocks: %u, total unfreed memory %f MB\n",
39 leaked_blocks,
40 double(mem_in_use) / 1024 / 1024);
42
43 /* In guarded implementation, the fact that all allocated memory blocks are stored in the
44 * static `membase` listbase is enough for LSAN to not detect them as leaks. Clearing it solves
45 * that issue. */
47
48 if (fail_on_memleak) {
49 /* There are many other ways to change the exit code to failure here:
50 * - Make the destructor `noexcept(false)` and throw an exception.
51 * - Call exit(EXIT_FAILURE).
52 * - Call terminate().
53 */
54 abort();
55 }
56 }
57};
58} // namespace
59
61{
62 /* Calling this ensures that the memory usage counters outlive the memory leak detection. */
64
65 /* Ensure that the static memleak data storage is initialized before the #MemLeakPrinter one, so
66 * that it outlives the memory leak detection. */
67 std::any any_data = std::make_any<int>(0);
69
79 static MemLeakPrinter printer;
80}
81
83{
84 fail_on_memleak = true;
85}
86
88{
89 static std::mutex mutex;
90 static std::vector<std::any> data_vec;
91 std::lock_guard lock{mutex};
92 data_vec.push_back(std::move(data));
93}
unsigned int uint
Read Guarded memory(de)allocation.
volatile int lock
BMesh const char void * data
ThreadMutex mutex
#define printf(...)
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:70
void(* mem_clearmemlist)(void)
Definition mallocn.cc:75
uint(* MEM_get_memory_blocks_in_use)(void)
Definition mallocn.cc:71
void(* MEM_printmemlist)(void)
Definition mallocn.cc:64
static size_t mem_in_use
void memory_usage_init(void)
void add_memleak_data(std::any data)