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.18.3
+version:             0.18.4
 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
diff --git a/src/Data/GI/Base/GParamSpec.hsc b/src/Data/GI/Base/GParamSpec.hsc
--- a/src/Data/GI/Base/GParamSpec.hsc
+++ b/src/Data/GI/Base/GParamSpec.hsc
@@ -8,9 +8,10 @@
     ) where
 
 import Foreign.Ptr
-import Foreign.ForeignPtr
+import Foreign.ForeignPtr (withForeignPtr)
 import Control.Monad (void)
 
+import Data.GI.Base.ManagedPtr (newManagedPtr)
 import Data.GI.Base.BasicTypes (GParamSpec(..))
 
 #include <glib-object.h>
@@ -31,14 +32,14 @@
 wrapGParamSpecPtr :: Ptr GParamSpec -> IO GParamSpec
 wrapGParamSpecPtr ptr = do
   void $ g_param_spec_ref_sink ptr
-  fPtr <- newForeignPtr ptr_to_g_param_spec_unref ptr
+  fPtr <- newManagedPtr ptr_to_g_param_spec_unref ptr
   return $! GParamSpec fPtr
 
 -- | Construct a Haskell wrapper for the given 'GParamSpec', without
 -- assuming ownership.
 newGParamSpecFromPtr :: Ptr GParamSpec -> IO GParamSpec
 newGParamSpecFromPtr ptr = do
-  fPtr <- g_param_spec_ref ptr >>= newForeignPtr ptr_to_g_param_spec_unref
+  fPtr <- g_param_spec_ref ptr >>= newManagedPtr ptr_to_g_param_spec_unref
   return $! GParamSpec fPtr
 
 -- | Add a reference to the given 'GParamSpec'.
diff --git a/src/Data/GI/Base/GVariant.hsc b/src/Data/GI/Base/GVariant.hsc
--- a/src/Data/GI/Base/GVariant.hsc
+++ b/src/Data/GI/Base/GVariant.hsc
@@ -151,11 +151,12 @@
 import System.IO.Unsafe (unsafePerformIO)
 import Foreign.C
 import Foreign.Ptr
-import Foreign.ForeignPtr
+import Foreign.ForeignPtr (withForeignPtr)
 
 import Data.GI.Base.BasicTypes (GVariant(..))
 import Data.GI.Base.BasicConversions
-import Data.GI.Base.ManagedPtr (withManagedPtr, withManagedPtrList)
+import Data.GI.Base.ManagedPtr (withManagedPtr, withManagedPtrList,
+                                newManagedPtr)
 import Data.GI.Base.Utils (freeMem)
 
 -- | An alias for @Nothing :: Maybe GVariant@ to save some typing.
@@ -262,14 +263,14 @@
 wrapGVariantPtr ptr = do
   floating <- g_variant_is_floating ptr
   when (floating /= 0) $ void $ g_variant_ref_sink ptr
-  fPtr <- newForeignPtr ptr_to_g_variant_unref ptr
+  fPtr <- newManagedPtr ptr_to_g_variant_unref ptr
   return $! GVariant fPtr
 
 -- | Construct a Haskell wrapper for the given 'GVariant', without
 -- assuming ownership.
 newGVariantFromPtr :: Ptr GVariant -> IO GVariant
 newGVariantFromPtr ptr = do
-  fPtr <- g_variant_ref ptr >>= newForeignPtr ptr_to_g_variant_unref
+  fPtr <- g_variant_ref ptr >>= newManagedPtr ptr_to_g_variant_unref
   return $! GVariant fPtr
 
 -- | Add a reference to the given 'GVariant'.
diff --git a/src/Data/GI/Base/ManagedPtr.hs b/src/Data/GI/Base/ManagedPtr.hs
--- a/src/Data/GI/Base/ManagedPtr.hs
+++ b/src/Data/GI/Base/ManagedPtr.hs
@@ -15,7 +15,8 @@
 module Data.GI.Base.ManagedPtr
     (
     -- * Managed pointers
-      withManagedPtr
+      newManagedPtr
+    , withManagedPtr
     , maybeWithManagedPtr
     , withManagedPtrList
     , unsafeManagedPtrGetPtr
@@ -48,11 +49,11 @@
 
 import Data.Coerce (coerce)
 
-import Foreign (poke)
 import Foreign.C (CInt(..))
 import Foreign.Ptr (Ptr, FunPtr, castPtr, nullPtr)
-import Foreign.ForeignPtr (ForeignPtr, newForeignPtr, newForeignPtrEnv,
+import Foreign.ForeignPtr (ForeignPtr, FinalizerPtr,
                            touchForeignPtr, newForeignPtr_)
+import qualified Foreign.Concurrent as FC
 import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
 
 import Data.GI.Base.BasicTypes
@@ -69,6 +70,14 @@
 type HasCallStack = (() :: Constraint)
 #endif
 
+foreign import ccall "dynamic"
+   mkFinalizer :: FinalizerPtr a -> Ptr a -> IO ()
+
+-- | A thin wrapper over `Foreign.Concurrent.newForeignPtr`.
+newManagedPtr :: FinalizerPtr a -> Ptr a -> IO (ForeignPtr a)
+newManagedPtr finalizer ptr = do
+  FC.newForeignPtr ptr (mkFinalizer finalizer ptr)
+
 -- | Perform an IO action on the 'Ptr' inside a managed pointer.
 withManagedPtr :: ForeignPtrNewtype a => a -> (Ptr a -> IO c) -> IO c
 withManagedPtr managed action = do
@@ -162,7 +171,7 @@
 newObject :: (GObject a, GObject b) => (ForeignPtr a -> a) -> Ptr b -> IO a
 newObject constructor ptr = do
   void $ g_object_ref ptr
-  fPtr <- newForeignPtr ptr_to_g_object_unref $ castPtr ptr
+  fPtr <- newManagedPtr ptr_to_g_object_unref $ castPtr ptr
   return $! constructor fPtr
 
 foreign import ccall "g_object_ref_sink" g_object_ref_sink ::
@@ -194,7 +203,7 @@
 wrapObject constructor ptr = do
   when (gobjectIsInitiallyUnowned (undefined :: a)) $
        void $ g_object_ref_sink ptr
-  fPtr <- newForeignPtr ptr_to_g_object_unref $ castPtr ptr
+  fPtr <- newManagedPtr ptr_to_g_object_unref $ castPtr ptr
   return $! constructor fPtr
 
 -- | Increase the reference count of the given 'GObject'.
@@ -210,8 +219,8 @@
 unrefObject :: GObject a => a -> IO ()
 unrefObject obj = withManagedPtr obj g_object_unref
 
-foreign import ccall "& boxed_free_helper" boxed_free_helper ::
-    FunPtr (Ptr env -> Ptr a -> IO ())
+foreign import ccall "boxed_free_helper" boxed_free_helper ::
+    CGType -> Ptr a -> IO ()
 
 foreign import ccall "g_boxed_copy" g_boxed_copy ::
     CGType -> Ptr a -> IO (Ptr a)
@@ -221,10 +230,8 @@
 newBoxed :: forall a. BoxedObject a => (ForeignPtr a -> a) -> Ptr a -> IO a
 newBoxed constructor ptr = do
   GType gtype <- boxedType (undefined :: a)
-  env <- allocMem :: IO (Ptr CGType)   -- Will be freed by boxed_free_helper
-  poke env gtype
   ptr' <- g_boxed_copy gtype ptr
-  fPtr <- newForeignPtrEnv boxed_free_helper env ptr'
+  fPtr <- FC.newForeignPtr ptr' (boxed_free_helper gtype ptr')
   return $! constructor fPtr
 
 -- | Like 'newBoxed', but we do not make a copy (we "steal" the passed
@@ -232,9 +239,7 @@
 wrapBoxed :: forall a. BoxedObject a => (ForeignPtr a -> a) -> Ptr a -> IO a
 wrapBoxed constructor ptr = do
   GType gtype <- boxedType (undefined :: a)
-  env <- allocMem :: IO (Ptr CGType)   -- Will be freed by boxed_free_helper
-  poke env gtype
-  fPtr <- newForeignPtrEnv boxed_free_helper env ptr
+  fPtr <- FC.newForeignPtr ptr (boxed_free_helper gtype ptr)
   return $! constructor fPtr
 
 -- | Make a copy of the given boxed object.
@@ -264,7 +269,7 @@
 wrapPtr constructor ptr = do
   fPtr <- case wrappedPtrFree of
             Nothing -> newForeignPtr_ ptr
-            Just finalizer -> newForeignPtr finalizer ptr
+            Just finalizer -> newManagedPtr finalizer ptr
   return $! constructor fPtr
 
 -- | Wrap a pointer, making a copy of the data.
@@ -273,7 +278,7 @@
   ptr' <- wrappedPtrCopy ptr
   fPtr <- case wrappedPtrFree of
             Nothing -> newForeignPtr_ ptr
-            Just finalizer -> newForeignPtr finalizer ptr'
+            Just finalizer -> newManagedPtr finalizer ptr'
   return $! constructor fPtr
 
 -- | Make a copy of a wrapped pointer using @memcpy@ into a freshly
diff --git a/src/Data/GI/Base/ShortPrelude.hs b/src/Data/GI/Base/ShortPrelude.hs
--- a/src/Data/GI/Base/ShortPrelude.hs
+++ b/src/Data/GI/Base/ShortPrelude.hs
@@ -67,7 +67,7 @@
 import Foreign.C (CInt(..), CUInt(..), CFloat(..), CDouble(..), CString, CIntPtr(..), CUIntPtr(..), CLong(..), CULong(..))
 import Foreign.Ptr (Ptr, plusPtr, FunPtr, nullPtr,
                     castFunPtrToPtr, castPtrToFunPtr)
-import Foreign.ForeignPtr (ForeignPtr, newForeignPtr_)
+import Foreign.ForeignPtr (ForeignPtr)
 import Foreign.ForeignPtr.Unsafe (unsafeForeignPtrToPtr)
 import Foreign.Storable (peek, poke, sizeOf)
 import Control.Applicative ((<$>))
diff --git a/src/c/hsgclosure.c b/src/c/hsgclosure.c
--- a/src/c/hsgclosure.c
+++ b/src/c/hsgclosure.c
@@ -33,15 +33,14 @@
 }
 
 /* Auxiliary function for freeing boxed types */
-void boxed_free_helper (GType *gtype, void *boxed)
+void boxed_free_helper (GType gtype, void *boxed)
 {
   if (print_debug_info()) {
     fprintf(stderr, "Freeing a boxed object at %p\n", boxed);
-    fprintf(stderr, "\tIt is of type %s\n", g_type_name(*gtype));
+    fprintf(stderr, "\tIt is of type %s\n", g_type_name(gtype));
   }
 
-  g_boxed_free (*gtype, boxed);
-  g_free (gtype);
+  g_boxed_free (gtype, boxed);
 
   if (print_debug_info()) {
     fprintf(stderr, "\tdone\n");
