diff --git a/ChangeLog.md b/ChangeLog.md
--- a/ChangeLog.md
+++ b/ChangeLog.md
@@ -1,6 +1,12 @@
+### 0.22.1
+
++ Fix a memory allocation error in [GClosure](https://hackage.haskell.org/package/haskell-gi-base-0.22.0/docs/Data-GI-Base.html#t:GClosure) that could lead to crashes.
+
 ### 0.22.0
 
 + Require base >= 0.4.9 (GHC version >= 8.0), so that we can use TypeApplications.
+
++ Make [GClosure](https://hackage.haskell.org/package/haskell-gi-base-0.22.0/docs/Data-GI-Base.html#t:GClosure) a primitive type, and make it depend on a phantom parameter to increase type safety.
 
 ### 0.21.5
 
diff --git a/Data/GI/Base/GClosure.hs b/Data/GI/Base/GClosure.hs
--- a/Data/GI/Base/GClosure.hs
+++ b/Data/GI/Base/GClosure.hs
@@ -9,14 +9,16 @@
     , disownGClosure
     ) where
 
-import Foreign
+import Foreign.Ptr (Ptr, FunPtr, nullPtr)
+import Foreign.C (CInt(..))
 
+import Control.Monad (when)
 import Control.Monad.IO.Class (MonadIO, liftIO)
 
 import Data.GI.Base.BasicTypes
 import Data.GI.Base.CallStack (HasCallStack)
-import Data.GI.Base.ManagedPtr (newBoxed, wrapBoxed, freeBoxed,
-                                disownManagedPtr)
+import Data.GI.Base.ManagedPtr (newBoxed, newManagedPtr',
+                                disownManagedPtr, withManagedPtr)
 
 -- | The basic type. This corresponds to a wrapped @GClosure@ on the C
 -- side, which is a boxed object.
@@ -48,9 +50,24 @@
   closure <- g_cclosure_new ptr nullPtr ptr_to_release_closure
   wrapGClosurePtr closure
 
+foreign import ccall g_closure_ref :: Ptr (GClosure a) -> IO (Ptr (GClosure a))
+foreign import ccall g_closure_sink :: Ptr (GClosure a) -> IO ()
+foreign import ccall g_closure_unref :: Ptr (GClosure a) -> IO ()
+foreign import ccall "&g_closure_unref" ptr_to_g_closure_unref ::
+        FunPtr (Ptr (GClosure a) -> IO ())
+
+foreign import ccall "haskell_gi_g_closure_is_floating" g_closure_is_floating ::
+        Ptr (GClosure a) -> IO CInt
+
 -- | Take ownership of a passed in 'Ptr' to a 'GClosure'.
 wrapGClosurePtr :: Ptr (GClosure a) -> IO (GClosure a)
-wrapGClosurePtr = wrapBoxed GClosure
+wrapGClosurePtr closurePtr = do
+  floating <- g_closure_is_floating closurePtr
+  when (floating /= 0) $ do
+    _ <- g_closure_ref closurePtr
+    g_closure_sink closurePtr
+  fPtr <- newManagedPtr' ptr_to_g_closure_unref closurePtr
+  return $! GClosure fPtr
 
 -- | Construct a Haskell wrapper for the 'GClosure', without assuming
 -- ownership.
@@ -60,7 +77,7 @@
 -- | Decrease the reference count of the given 'GClosure'. If the
 -- reference count reaches 0 the memory will be released.
 unrefGClosure :: (HasCallStack, MonadIO m) => GClosure a -> m ()
-unrefGClosure closure = liftIO $ freeBoxed closure
+unrefGClosure closure = liftIO $ withManagedPtr closure g_closure_unref
 
 -- | Disown (that is, remove from te purview of the Haskell Garbage
 -- Collector) the given 'GClosure'.
diff --git a/c/hsgclosure.c b/c/hsgclosure.c
--- a/c/hsgclosure.c
+++ b/c/hsgclosure.c
@@ -365,3 +365,10 @@
   dbg_log("\tDone.\n");
   unlock_log();
 }
+
+/* Check whether the given closure is floating */
+gboolean
+haskell_gi_g_closure_is_floating (GClosure *closure)
+{
+  return !!(closure->floating);
+}
diff --git a/haskell-gi-base.cabal b/haskell-gi-base.cabal
--- a/haskell-gi-base.cabal
+++ b/haskell-gi-base.cabal
@@ -1,5 +1,5 @@
 name:                haskell-gi-base
-version:             0.22.0
+version:             0.22.1
 synopsis:            Foundation for libraries generated by haskell-gi
 description:         Foundation for libraries generated by haskell-gi
 homepage:            https://github.com/haskell-gi/haskell-gi-base
