diff --git a/src/libcamera/device_enumerator.cpp b/src/libcamera/device_enumerator.cpp
index 8100972a8d04..149ffbf9aea6 100644
--- a/src/libcamera/device_enumerator.cpp
+++ b/src/libcamera/device_enumerator.cpp
@@ -166,12 +166,10 @@ std::unique_ptr<DeviceEnumerator> DeviceEnumerator::create()
 
 DeviceEnumerator::~DeviceEnumerator()
 {
-	for (MediaDevice *dev : devices_) {
-		if (dev->busy())
+	for (std::shared_ptr<MediaDevice> media : devices_) {
+		if (media->busy())
 			LOG(DeviceEnumerator, Error)
 				<< "Removing media device while still in use";
-
-		delete dev;
 	}
 }
 
@@ -211,7 +209,7 @@ DeviceEnumerator::~DeviceEnumerator()
  */
 int DeviceEnumerator::addDevice(const std::string &deviceNode)
 {
-	MediaDevice *media = new MediaDevice(deviceNode);
+	std::shared_ptr<MediaDevice> media = std::make_shared<MediaDevice>(deviceNode);
 
 	int ret = media->open();
 	if (ret < 0)
@@ -243,9 +241,10 @@ int DeviceEnumerator::addDevice(const std::string &deviceNode)
 			return ret;
 	}
 
-	devices_.push_back(media);
 	media->close();
 
+	devices_.push_back(std::move(media));
+
 	return 0;
 }
 
@@ -260,17 +259,17 @@ int DeviceEnumerator::addDevice(const std::string &deviceNode)
  *
  * \return pointer to the matching MediaDevice, or nullptr if no match is found
  */
-MediaDevice *DeviceEnumerator::search(const DeviceMatch &dm)
+std::shared_ptr<MediaDevice> DeviceEnumerator::search(const DeviceMatch &dm)
 {
-	for (MediaDevice *dev : devices_) {
-		if (dev->busy())
+	for (std::shared_ptr<MediaDevice> media : devices_) {
+		if (media->busy())
 			continue;
 
-		if (dm.match(dev)) {
+		if (dm.match(media.get())) {
 			LOG(DeviceEnumerator, Debug)
 				<< "Successful match for media device \""
-				<< dev->driver() << "\"";
-			return dev;
+				<< media->driver() << "\"";
+			return std::move(media);
 		}
 	}
 
diff --git a/src/libcamera/include/device_enumerator.h b/src/libcamera/include/device_enumerator.h
index 40c7750b49fc..3f87a6255303 100644
--- a/src/libcamera/include/device_enumerator.h
+++ b/src/libcamera/include/device_enumerator.h
@@ -42,13 +42,13 @@ public:
 	virtual int init() = 0;
 	virtual int enumerate() = 0;
 
-	MediaDevice *search(const DeviceMatch &dm);
+	std::shared_ptr<MediaDevice> search(const DeviceMatch &dm);
 
 protected:
 	int addDevice(const std::string &deviceNode);
 
 private:
-	std::vector<MediaDevice *> devices_;
+	std::vector<std::shared_ptr<MediaDevice>> devices_;
 
 	virtual std::string lookupDeviceNode(int major, int minor) = 0;
 };
diff --git a/src/libcamera/pipeline/ipu3/ipu3.cpp b/src/libcamera/pipeline/ipu3/ipu3.cpp
index 13ff7da4c99e..9831f74fe53f 100644
--- a/src/libcamera/pipeline/ipu3/ipu3.cpp
+++ b/src/libcamera/pipeline/ipu3/ipu3.cpp
@@ -29,8 +29,8 @@ public:
 	bool match(DeviceEnumerator *enumerator);
 
 private:
-	MediaDevice *cio2_;
-	MediaDevice *imgu_;
+	std::shared_ptr<MediaDevice> cio2_;
+	std::shared_ptr<MediaDevice> imgu_;
 
 	void registerCameras();
 };
@@ -47,9 +47,6 @@ PipelineHandlerIPU3::~PipelineHandlerIPU3()
 
 	if (imgu_)
 		imgu_->release();
-
-	cio2_ = nullptr;
-	imgu_ = nullptr;
 }
 
 bool PipelineHandlerIPU3::match(DeviceEnumerator *enumerator)
@@ -78,11 +75,11 @@ bool PipelineHandlerIPU3::match(DeviceEnumerator *enumerator)
 	imgu_dm.add("ipu3-imgu 1 viewfinder");
 	imgu_dm.add("ipu3-imgu 1 3a stat");
 
-	cio2_ = enumerator->search(cio2_dm);
+	cio2_ = std::move(enumerator->search(cio2_dm));
 	if (!cio2_)
 		return false;
 
-	imgu_ = enumerator->search(imgu_dm);
+	imgu_ = std::move(enumerator->search(imgu_dm));
 	if (!imgu_)
 		return false;
 
diff --git a/src/libcamera/pipeline/uvcvideo.cpp b/src/libcamera/pipeline/uvcvideo.cpp
index 3ebc074093ab..73bad6714bb4 100644
--- a/src/libcamera/pipeline/uvcvideo.cpp
+++ b/src/libcamera/pipeline/uvcvideo.cpp
@@ -23,7 +23,7 @@ public:
 	bool match(DeviceEnumerator *enumerator);
 
 private:
-	MediaDevice *dev_;
+	std::shared_ptr<MediaDevice> dev_;
 };
 
 PipelineHandlerUVC::PipelineHandlerUVC(CameraManager *manager)
@@ -41,7 +41,7 @@ bool PipelineHandlerUVC::match(DeviceEnumerator *enumerator)
 {
 	DeviceMatch dm("uvcvideo");
 
-	dev_ = enumerator->search(dm);
+	dev_ = std::move(enumerator->search(dm));
 
 	if (!dev_)
 		return false;
diff --git a/src/libcamera/pipeline/vimc.cpp b/src/libcamera/pipeline/vimc.cpp
index 68bfe9b12ab6..521b20d3a120 100644
--- a/src/libcamera/pipeline/vimc.cpp
+++ b/src/libcamera/pipeline/vimc.cpp
@@ -23,7 +23,7 @@ public:
 	bool match(DeviceEnumerator *enumerator);
 
 private:
-	MediaDevice *dev_;
+	std::shared_ptr<MediaDevice> dev_;
 };
 
 PipeHandlerVimc::PipeHandlerVimc(CameraManager *manager)
@@ -51,7 +51,7 @@ bool PipeHandlerVimc::match(DeviceEnumerator *enumerator)
 	dm.add("RGB/YUV Input");
 	dm.add("Scaler");
 
-	dev_ = enumerator->search(dm);
+	dev_ = std::move(enumerator->search(dm));
 	if (!dev_)
 		return false;
 
diff --git a/test/media_device/media_device_link_test.cpp b/test/media_device/media_device_link_test.cpp
index ac5b632f8ed1..58a55cdfee63 100644
--- a/test/media_device/media_device_link_test.cpp
+++ b/test/media_device/media_device_link_test.cpp
@@ -240,7 +240,7 @@ class MediaDeviceLinkTest : public Test
 
 private:
 	unique_ptr<DeviceEnumerator> enumerator;
-	MediaDevice *dev_;
+	shared_ptr<MediaDevice> dev_;
 };
 
 TEST_REGISTER(MediaDeviceLinkTest);
diff --git a/test/pipeline/ipu3/ipu3_pipeline_test.cpp b/test/pipeline/ipu3/ipu3_pipeline_test.cpp
index 482c12499a86..953f0233cde4 100644
--- a/test/pipeline/ipu3/ipu3_pipeline_test.cpp
+++ b/test/pipeline/ipu3/ipu3_pipeline_test.cpp
@@ -65,7 +65,7 @@ int IPU3PipelineTest::init()
 		return TestSkip;
 	}
 
-	MediaDevice *cio2 = enumerator->search(cio2_dm);
+	std::shared_ptr<MediaDevice> cio2 = enumerator->search(cio2_dm);
 	if (!cio2) {
 		cerr << "Failed to find IPU3 CIO2: test skip" << endl;
 		return TestSkip;
