Using JUCE_HEAVYWEIGHT_LEAK_DETECTOR on JUCE classes

The documentation for JUCE_HEAVYWEIGHT_LEAK_DETECTOR says:

To use it, simply declare a JUCE_HEAVYWEIGHT_LEAK_DETECTOR (YourClassName) inside a private section of the class declaration.

But if we’re leaking a juce::MemoryBlock and want to track that, we can’t just change JUCE_LEAK_DETECTOR (MemoryBlock) to use the heavyweight variant, because juce_HeavyweightLeakedObjectDetector.h isn’t included yet.
But if we try to add the include in juce_MemoryBlock.h it doesn’t work because the JUCE modules are written in an unusual way where each file doesn’t include what it requires and there are no #pragma once in header files.
But I can make it work with a much larger patch (9 files changed, 31 insertions(+), 1 deletion(-)) adding various #includes and #pragma once:

diff --git a/modules/juce_core/containers/juce_Array.h b/modules/juce_core/containers/juce_Array.h
index 05f957997..e2658fa71 100644
--- a/modules/juce_core/containers/juce_Array.h
+++ b/modules/juce_core/containers/juce_Array.h
@@ -20,6 +20,12 @@
   ==============================================================================
 */
 
+#pragma once
+
+#include "juce_ArrayBase.h"
+#include "../containers/juce_ElementComparator.h"
+#include "../threads/juce_CriticalSection.h"
+
 namespace juce
 {
 
diff --git a/modules/juce_core/containers/juce_ArrayBase.h b/modules/juce_core/containers/juce_ArrayBase.h
index 515bf0f24..f70c38bbc 100644
--- a/modules/juce_core/containers/juce_ArrayBase.h
+++ b/modules/juce_core/containers/juce_ArrayBase.h
@@ -20,6 +20,8 @@
   ==============================================================================
 */
 
+#pragma once
+
 namespace juce
 {
 
diff --git a/modules/juce_core/containers/juce_ElementComparator.h b/modules/juce_core/containers/juce_ElementComparator.h
index 5bf7d5e12..57bcc2489 100644
--- a/modules/juce_core/containers/juce_ElementComparator.h
+++ b/modules/juce_core/containers/juce_ElementComparator.h
@@ -20,6 +20,8 @@
   ==============================================================================
 */
 
+#pragma once
+
 namespace juce
 {
 
diff --git a/modules/juce_core/memory/juce_HeavyweightLeakedObjectDetector.h b/modules/juce_core/memory/juce_HeavyweightLeakedObjectDetector.h
index 0bc2b5344..599efe19c 100644
--- a/modules/juce_core/memory/juce_HeavyweightLeakedObjectDetector.h
+++ b/modules/juce_core/memory/juce_HeavyweightLeakedObjectDetector.h
@@ -20,6 +20,10 @@
   ==============================================================================
 */
 
+#pragma once
+
+#include "../juce_core/system/juce_SystemStats.h"
+
 namespace juce
 {
 
diff --git a/modules/juce_core/memory/juce_MemoryBlock.h b/modules/juce_core/memory/juce_MemoryBlock.h
index 0a2d1fd97..185dc8dd4 100644
--- a/modules/juce_core/memory/juce_MemoryBlock.h
+++ b/modules/juce_core/memory/juce_MemoryBlock.h
@@ -20,6 +20,8 @@
   ==============================================================================
 */
 
+#include "juce_HeavyweightLeakedObjectDetector.h"
+
 namespace juce
 {
 
@@ -284,7 +286,7 @@ private:
     HeapBlockType data;
     size_t size = 0;
 
-    JUCE_LEAK_DETECTOR (MemoryBlock)
+    JUCE_HEAVYWEIGHT_LEAK_DETECTOR (MemoryBlock)
 };
 
 } // namespace juce
diff --git a/modules/juce_core/system/juce_SystemStats.h b/modules/juce_core/system/juce_SystemStats.h
index 24b64c094..175eb2fb2 100644
--- a/modules/juce_core/system/juce_SystemStats.h
+++ b/modules/juce_core/system/juce_SystemStats.h
@@ -20,6 +20,10 @@
   ==============================================================================
 */
 
+#pragma once
+
+#include "../text/juce_StringArray.h"
+
 namespace juce
 {
 
diff --git a/modules/juce_core/text/juce_StringArray.h b/modules/juce_core/text/juce_StringArray.h
index 2f198f169..6cfef5a38 100644
--- a/modules/juce_core/text/juce_StringArray.h
+++ b/modules/juce_core/text/juce_StringArray.h
@@ -20,6 +20,10 @@
   ==============================================================================
 */
 
+#pragma once
+
+#include "../containers/juce_Array.h"
+
 namespace juce
 {
 
diff --git a/modules/juce_core/threads/juce_CriticalSection.h b/modules/juce_core/threads/juce_CriticalSection.h
index 9d5e12dee..19626a50c 100644
--- a/modules/juce_core/threads/juce_CriticalSection.h
+++ b/modules/juce_core/threads/juce_CriticalSection.h
@@ -20,6 +20,10 @@
   ==============================================================================
 */
 
+#pragma once
+
+#include "juce_ScopedLock.h"
+
 namespace juce
 {
 
diff --git a/modules/juce_core/threads/juce_ScopedLock.h b/modules/juce_core/threads/juce_ScopedLock.h
index 6c1ba887f..2a1a8ce18 100644
--- a/modules/juce_core/threads/juce_ScopedLock.h
+++ b/modules/juce_core/threads/juce_ScopedLock.h
@@ -20,6 +20,8 @@
   ==============================================================================
 */
 
+#pragma once
+
 namespace juce
 {
 

Is there a better or more ergonomic way to do it? Why is JUCE structured in this unusual way?

1 Like

JUCE uses a Unity build architecture for better build times. We generally don’t include headers within headers as we rely on the order of the includes in the parent source file. This removes the header spaghetti problem that can occur in large C++ projects.

The ‘correct’ way to handle this change is to move the juce_HeavyweightLeakedObjectDetector.h include directive in juce_core.h further up the list.

Using the heavyweight leak detector on common internal objects might lead to performance issues and false positives, it’s not recommended.

1 Like