diff --git a/rts/CheckUnload.c b/rts/CheckUnload.c
index 3140b571b83008d55759d29193562da7712e3b6d..e7e04bcd388dcc57faba2f5e79c69d64377ebc34 100644
--- a/rts/CheckUnload.c
+++ b/rts/CheckUnload.c
@@ -165,6 +165,18 @@ ObjectCode *loaded_objects;
 // map static closures to their ObjectCode.
 static OCSectionIndices *global_s_indices = NULL;
 
+// Is it safe for us to unload code?
+static bool safeToUnload(void)
+{
+    if (RtsFlags.ProfFlags.doHeapProfile != NO_HEAP_PROFILING) {
+        // We mustn't unload anything as the heap census may contain
+        // references into static data (e.g. cost centre names).
+        // See #24512.
+        return false;
+    }
+    return true;
+}
+
 static OCSectionIndices *createOCSectionIndices(void)
 {
     // TODO (osa): Maybe initialize as empty (without allocation) and allocate
@@ -457,6 +469,8 @@ void checkUnload(void)
 {
     if (global_s_indices == NULL) {
         return;
+    } else if (!safeToUnload()) {
+        return;
     }
 
     // At this point we've marked all dynamically loaded static objects