diff --git a/libpurple/account.c b/libpurple/account.c
--- a/libpurple/account.c
+++ b/libpurple/account.c
@@ -28,6 +28,7 @@
 #include "core.h"
 #include "dbus-maybe.h"
 #include "debug.h"
+#include "glibcompat.h"
 #include "network.h"
 #include "notify.h"
 #include "pounce.h"
@@ -1849,8 +1850,8 @@
 	/* Out with the old... */
 	if (account->status_types != NULL)
 	{
-		g_list_foreach(account->status_types, (GFunc)purple_status_type_destroy, NULL);
-		g_list_free(account->status_types);
+		g_list_free_full(account->status_types,
+		                 (GDestroyNotify)purple_status_type_destroy);
 	}
 
 	/* In with the new... */
diff --git a/libpurple/blist.c b/libpurple/blist.c
--- a/libpurple/blist.c
+++ b/libpurple/blist.c
@@ -27,6 +27,7 @@
 #include "conversation.h"
 #include "dbus-maybe.h"
 #include "debug.h"
+#include "glibcompat.h"
 #include "notify.h"
 #include "pounce.h"
 #include "prefs.h"
@@ -2422,8 +2423,7 @@
 		GList *parts = prpl_info->chat_info(purple_account_get_connection(chat->account));
 		pce = parts->data;
 		ret = g_hash_table_lookup(chat->components, pce->identifier);
-		g_list_foreach(parts, (GFunc)g_free, NULL);
-		g_list_free(parts);
+		g_list_free_full(parts, (GDestroyNotify)g_free);
 	}
 
 	return ret;
@@ -2570,8 +2570,7 @@
 				pce = parts->data;
 				chat_name = g_hash_table_lookup(chat->components,
 												pce->identifier);
-				g_list_foreach(parts, (GFunc)g_free, NULL);
-				g_list_free(parts);
+				g_list_free_full(parts, (GDestroyNotify)g_free);
 
 				if (chat->account == account && chat_name != NULL &&
 					purple_strequal(purple_normalize(account, chat_name), normname)) {
diff --git a/libpurple/certificate.c b/libpurple/certificate.c
--- a/libpurple/certificate.c
+++ b/libpurple/certificate.c
@@ -30,6 +30,7 @@
 #include "certificate.h"
 #include "dbus-maybe.h"
 #include "debug.h"
+#include "glibcompat.h"
 #include "request.h"
 #include "signals.h"
 #include "util.h"
@@ -957,8 +958,7 @@
 	x509_ca_certs = NULL;
 	x509_ca_initialized = FALSE;
 	/** TODO: the cert store in the SSL implementation wouldn't be cleared by this */
-	g_list_foreach(x509_ca_paths, (GFunc)g_free, NULL);
-	g_list_free(x509_ca_paths);
+	g_list_free_full(x509_ca_paths, (GDestroyNotify)g_free);
 	x509_ca_paths = NULL;
 }
 
@@ -1796,8 +1796,7 @@
 	if (valid == FALSE)
 		flags |= PURPLE_CERTIFICATE_INVALID_CHAIN;
 
-	g_slist_foreach(ca_crts, (GFunc)purple_certificate_destroy, NULL);
-	g_slist_free(ca_crts);
+	g_slist_free_full(ca_crts, (GDestroyNotify)purple_certificate_destroy);
 	g_byte_array_free(last_fpr, TRUE);
 
 	x509_tls_cached_check_subject_name(vrq, flags);
diff --git a/libpurple/conversation.c b/libpurple/conversation.c
--- a/libpurple/conversation.c
+++ b/libpurple/conversation.c
@@ -25,6 +25,7 @@
 #include "conversation.h"
 #include "dbus-maybe.h"
 #include "debug.h"
+#include "glibcompat.h"
 #include "imgstore.h"
 #include "notify.h"
 #include "prefs.h"
@@ -288,13 +289,6 @@
 	g_free(msg);
 }
 
-static void
-message_history_free(GList *list)
-{
-	g_list_foreach(list, (GFunc)free_conv_message, NULL);
-	g_list_free(list);
-}
-
 /**************************************************************************
  * Conversation API
  **************************************************************************/
@@ -622,11 +616,10 @@
 		g_hash_table_destroy(conv->u.chat->users);
 		conv->u.chat->users = NULL;
 
-		g_list_foreach(conv->u.chat->in_room, (GFunc)purple_conv_chat_cb_destroy, NULL);
-		g_list_free(conv->u.chat->in_room);
-
-		g_list_foreach(conv->u.chat->ignored, (GFunc)g_free, NULL);
-		g_list_free(conv->u.chat->ignored);
+		g_list_free_full(conv->u.chat->in_room,
+		                 (GDestroyNotify)purple_conv_chat_cb_destroy);
+
+		g_list_free_full(conv->u.chat->ignored, (GDestroyNotify)g_free);
 
 		conv->u.chat->in_room = NULL;
 		conv->u.chat->ignored = NULL;
@@ -878,8 +871,7 @@
 {
 	g_return_if_fail(conv != NULL);
 
-	g_list_foreach(conv->logs, (GFunc)purple_log_free, NULL);
-	g_list_free(conv->logs);
+	g_list_free_full(conv->logs, (GDestroyNotify)purple_log_free);
 	conv->logs = NULL;
 }
 
@@ -2384,7 +2376,7 @@
 void purple_conversation_clear_message_history(PurpleConversation *conv)
 {
 	GList *list = conv->message_history;
-	message_history_free(list);
+	g_list_free_full(list, (GDestroyNotify)free_conv_message);
 	conv->message_history = NULL;
 
 	purple_signal_emit(purple_conversations_get_handle(),
diff --git a/libpurple/desktopitem.c b/libpurple/desktopitem.c
--- a/libpurple/desktopitem.c
+++ b/libpurple/desktopitem.c
@@ -59,6 +59,7 @@
 #include <string.h>
 #include <time.h>
 #include "desktopitem.h"
+#include "glibcompat.h"
 
 struct _PurpleDesktopItem {
 	int refcount;
@@ -1113,15 +1114,12 @@
 }
 
 static void
-free_section (gpointer data, gpointer user_data)
+free_section (Section *section)
 {
-	Section *section = data;
-
 	g_free (section->name);
 	section->name = NULL;
 
-	g_list_foreach (section->keys, (GFunc)g_free, NULL);
-	g_list_free (section->keys);
+	g_list_free_full(section->keys, (GDestroyNotify)g_free);
 	section->keys = NULL;
 
 	g_free (section);
@@ -1237,16 +1235,13 @@
 	if(item->refcount != 0)
 		return;
 
-	g_list_foreach (item->languages, (GFunc)g_free, NULL);
-	g_list_free (item->languages);
+	g_list_free_full(item->languages, (GDestroyNotify)g_free);
 	item->languages = NULL;
 
-	g_list_foreach (item->keys, (GFunc)g_free, NULL);
-	g_list_free (item->keys);
+	g_list_free_full(item->keys, (GDestroyNotify)g_free);
 	item->keys = NULL;
 
-	g_list_foreach (item->sections, free_section, NULL);
-	g_list_free (item->sections);
+	g_list_free_full(item->sections, (GDestroyNotify)free_section);
 	item->sections = NULL;
 
 	g_hash_table_destroy (item->main_hash);
diff --git a/libpurple/dnssrv.c b/libpurple/dnssrv.c
--- a/libpurple/dnssrv.c
+++ b/libpurple/dnssrv.c
@@ -22,6 +22,7 @@
  */
 #define _PURPLE_DNSSRV_C_
 
+#include "glibcompat.h"
 #include "internal.h"
 #include "util.h"
 
@@ -539,16 +540,16 @@
 							purple_debug_error("dnssrv","unable to read txt "
 									"response length: %s\n", g_strerror(errno));
 							size = 0;
-							g_list_foreach(responses, (GFunc)purple_txt_response_destroy, NULL);
-							g_list_free(responses);
+							g_list_free_full(responses,
+							                 (GDestroyNotify)purple_txt_response_destroy);
 							responses = NULL;
 							break;
 						}
 						if (len > MAX_ADDR_RESPONSE_LEN) {
 							purple_debug_error("dnssrv", "we've read invalid number\n");
 							size = 0;
-							g_list_foreach(responses, (GFunc)purple_txt_response_destroy, NULL);
-							g_list_free(responses);
+							g_list_free_full(responses,
+							                 (GDestroyNotify)purple_txt_response_destroy);
 							responses = NULL;
 							break;
 						}
@@ -562,8 +563,8 @@
 									"response: %s\n", g_strerror(errno));
 							size = 0;
 							purple_txt_response_destroy(res);
-							g_list_foreach(responses, (GFunc)purple_txt_response_destroy, NULL);
-							g_list_free(responses);
+							g_list_free_full(responses,
+							                 (GDestroyNotify)purple_txt_response_destroy);
 							responses = NULL;
 							break;
 						}
diff --git a/libpurple/glibcompat.h b/libpurple/glibcompat.h
--- a/libpurple/glibcompat.h
+++ b/libpurple/glibcompat.h
@@ -29,6 +29,30 @@
 
 #include <glib.h>
 
+#if !GLIB_CHECK_VERSION(2,28,0)
+static inline void
+g_list_free_full(GList *l, GDestroyNotify free_func) {
+	GList *ll = NULL;
+
+	for(ll = l; ll != NULL; ll = ll->next) {
+		free_func(ll->data);
+	}
+
+	g_list_free(l);
+}
+
+static inline void
+g_slist_free_full(GSList *l, GDestroyNotify free_func) {
+	GSList *ll = NULL;
+
+	for(ll = l; ll != NULL; ll = ll->next) {
+		free_func(ll->data);
+	}
+
+	g_slist_free(l);
+}
+#endif /* !GLIB_CHECK_VERSION(2,23,0) */
+
 #if !GLIB_CHECK_VERSION(2,32,0)
 # define G_GNUC_BEGIN_IGNORE_DEPRECATIONS
 # define G_GNUC_END_IGNORE_DEPRECATIONS
diff --git a/libpurple/notify.c b/libpurple/notify.c
--- a/libpurple/notify.c
+++ b/libpurple/notify.c
@@ -27,6 +27,7 @@
 
 #include "internal.h"
 #include "dbus-maybe.h"
+#include "glibcompat.h"
 #include "notify.h"
 
 static PurpleNotifyUiOps *notify_ui_ops = NULL;
@@ -262,8 +263,7 @@
 
 	for (l = results->rows; l; l = g_list_delete_link(l, l)) {
 		GList *row = l->data;
-		g_list_foreach(row, (GFunc)g_free, NULL);
-		g_list_free(row);
+		g_list_free_full(row, (GDestroyNotify)g_free);
 	}
 
 	for (l = results->columns; l; l = g_list_delete_link(l, l)) {
diff --git a/libpurple/pluginpref.c b/libpurple/pluginpref.c
--- a/libpurple/pluginpref.c
+++ b/libpurple/pluginpref.c
@@ -26,6 +26,7 @@
 #include <glib.h>
 
 #include "debug.h"
+#include "glibcompat.h"
 #include "internal.h"
 #include "pluginpref.h"
 #include "prefs.h"
@@ -65,8 +66,7 @@
 {
 	g_return_if_fail(frame != NULL);
 
-	g_list_foreach(frame->prefs, (GFunc)purple_plugin_pref_destroy, NULL);
-	g_list_free(frame->prefs);
+	g_list_free_full(frame->prefs, (GDestroyNotify)purple_plugin_pref_destroy);
 	g_free(frame);
 }
 
diff --git a/libpurple/prefs.c b/libpurple/prefs.c
--- a/libpurple/prefs.c
+++ b/libpurple/prefs.c
@@ -32,8 +32,9 @@
 #include <sys/types.h>
 #include <glib.h>
 #include "internal.h"
+#include "debug.h"
+#include "glibcompat.h"
 #include "prefs.h"
-#include "debug.h"
 #include "util.h"
 
 #ifdef _WIN32
@@ -587,10 +588,8 @@
 			break;
 		case PURPLE_PREF_STRING_LIST:
 		case PURPLE_PREF_PATH_LIST:
-			{
-				g_list_foreach(pref->value.stringlist, (GFunc)g_free, NULL);
-				g_list_free(pref->value.stringlist);
-			} break;
+			g_list_free_full(pref->value.stringlist, (GDestroyNotify)g_free);
+			break;
 		case PURPLE_PREF_NONE:
 			break;
 	}
@@ -997,8 +996,7 @@
 			return;
 		}
 
-		g_list_foreach(pref->value.stringlist, (GFunc)g_free, NULL);
-		g_list_free(pref->value.stringlist);
+		g_list_free_full(pref->value.stringlist, (GDestroyNotify)g_free);
 		pref->value.stringlist = NULL;
 
 		for(tmp = value; tmp; tmp = tmp->next) {
@@ -1063,8 +1061,7 @@
 			return;
 		}
 
-		g_list_foreach(pref->value.stringlist, (GFunc)g_free, NULL);
-		g_list_free(pref->value.stringlist);
+		g_list_free_full(pref->value.stringlist, (GDestroyNotify)g_free);
 		pref->value.stringlist = NULL;
 
 		for(tmp = value; tmp; tmp = tmp->next)
diff --git a/libpurple/protocols/jabber/jabber.c b/libpurple/protocols/jabber/jabber.c
--- a/libpurple/protocols/jabber/jabber.c
+++ b/libpurple/protocols/jabber/jabber.c
@@ -31,6 +31,7 @@
 #include "conversation.h"
 #include "debug.h"
 #include "dnssrv.h"
+#include "glibcompat.h"
 #include "imgstore.h"
 #include "message.h"
 #include "notify.h"
@@ -831,8 +832,7 @@
 	}
 
 	if (responses) {
-		g_list_foreach(responses, (GFunc)purple_txt_response_destroy, NULL);
-		g_list_free(responses);
+		g_list_free_full(responses, (GDestroyNotify)purple_txt_response_destroy);
 	}
 }
 
diff --git a/libpurple/protocols/jabber/presence.c b/libpurple/protocols/jabber/presence.c
--- a/libpurple/protocols/jabber/presence.c
+++ b/libpurple/protocols/jabber/presence.c
@@ -25,6 +25,7 @@
 #include "account.h"
 #include "conversation.h"
 #include "debug.h"
+#include "glibcompat.h"
 #include "notify.h"
 #include "request.h"
 #include "server.h"
@@ -491,16 +492,14 @@
 		g_free(userdata->from);
 		g_free(userdata);
 		if (exts) {
-			g_list_foreach(exts, (GFunc)g_free, NULL);
-			g_list_free(exts);
+			g_list_free_full(exts, g_free);
 		}
 		return;
 	}
 
 	/* Any old jbr->caps.info is owned by the caps code */
 	if (jbr->caps.exts) {
-		g_list_foreach(jbr->caps.exts, (GFunc)g_free, NULL);
-		g_list_free(jbr->caps.exts);
+		g_list_free_full(jbr->caps.exts, g_free);
 	}
 
 	jbr->caps.info = info;
diff --git a/libpurple/request.c b/libpurple/request.c
--- a/libpurple/request.c
+++ b/libpurple/request.c
@@ -62,8 +62,8 @@
 {
 	g_return_if_fail(fields != NULL);
 
-	g_list_foreach(fields->groups, (GFunc)purple_request_field_group_destroy, NULL);
-	g_list_free(fields->groups);
+	g_list_free_full(fields->groups,
+	                 (GDestroyNotify)purple_request_field_group_destroy);
 	g_list_free(fields->required_fields);
 	g_hash_table_destroy(fields->fields);
 	g_free(fields);
@@ -291,8 +291,8 @@
 
 	g_free(group->title);
 
-	g_list_foreach(group->fields, (GFunc)purple_request_field_destroy, NULL);
-	g_list_free(group->fields);
+	g_list_free_full(group->fields,
+	                 (GDestroyNotify)purple_request_field_destroy);
 
 	g_free(group);
 }
@@ -376,22 +376,19 @@
 	{
 		if (field->u.choice.labels != NULL)
 		{
-			g_list_foreach(field->u.choice.labels, (GFunc)g_free, NULL);
-			g_list_free(field->u.choice.labels);
+			g_list_free_full(field->u.choice.labels, (GDestroyNotify)g_free);
 		}
 	}
 	else if (field->type == PURPLE_REQUEST_FIELD_LIST)
 	{
 		if (field->u.list.items != NULL)
 		{
-			g_list_foreach(field->u.list.items, (GFunc)g_free, NULL);
-			g_list_free(field->u.list.items);
+			g_list_free_full(field->u.list.items, (GDestroyNotify)g_free);
 		}
 
 		if (field->u.list.selected != NULL)
 		{
-			g_list_foreach(field->u.list.selected, (GFunc)g_free, NULL);
-			g_list_free(field->u.list.selected);
+			g_list_free_full(field->u.list.selected, (GDestroyNotify)g_free);
 		}
 
 		g_hash_table_destroy(field->u.list.item_data);
@@ -919,8 +916,7 @@
 
 	if (field->u.list.selected != NULL)
 	{
-		g_list_foreach(field->u.list.selected, (GFunc)g_free, NULL);
-		g_list_free(field->u.list.selected);
+		g_list_free_full(field->u.list.selected, (GDestroyNotify)g_free);
 		field->u.list.selected = NULL;
 	}
 
diff --git a/libpurple/roomlist.c b/libpurple/roomlist.c
--- a/libpurple/roomlist.c
+++ b/libpurple/roomlist.c
@@ -29,6 +29,7 @@
 #include "account.h"
 #include "connection.h"
 #include "debug.h"
+#include "glibcompat.h"
 #include "roomlist.h"
 #include "server.h"
 
@@ -109,8 +110,8 @@
 	}
 	g_list_free(list->rooms);
 
-	g_list_foreach(list->fields, (GFunc)purple_roomlist_field_destroy, NULL);
-	g_list_free(list->fields);
+	g_list_free_full(list->fields,
+	                 (GDestroyNotify)purple_roomlist_field_destroy);
 
 	g_free(list);
 }
diff --git a/libpurple/signals.c b/libpurple/signals.c
--- a/libpurple/signals.c
+++ b/libpurple/signals.c
@@ -27,6 +27,7 @@
 
 #include "dbus-maybe.h"
 #include "debug.h"
+#include "glibcompat.h"
 #include "signals.h"
 #include "value.h"
 
@@ -84,8 +85,7 @@
 static void
 destroy_signal_data(PurpleSignalData *signal_data)
 {
-	g_list_foreach(signal_data->handlers, (GFunc)g_free, NULL);
-	g_list_free(signal_data->handlers);
+	g_list_free_full(signal_data->handlers, (GDestroyNotify)g_free);
 
 	if (signal_data->values != NULL)
 	{
diff --git a/libpurple/status.c b/libpurple/status.c
--- a/libpurple/status.c
+++ b/libpurple/status.c
@@ -31,6 +31,7 @@
 #include "core.h"
 #include "dbus-maybe.h"
 #include "debug.h"
+#include "glibcompat.h"
 #include "notify.h"
 #include "prefs.h"
 #include "status.h"
@@ -296,8 +297,8 @@
 	g_free(status_type->name);
 	g_free(status_type->primary_attr_id);
 
-	g_list_foreach(status_type->attrs, (GFunc)purple_status_attr_destroy, NULL);
-	g_list_free(status_type->attrs);
+	g_list_free_full(status_type->attrs,
+	                 (GDestroyNotify)purple_status_attr_destroy);
 
 	PURPLE_DBUS_UNREGISTER_POINTER(status_type);
 	g_free(status_type);
@@ -1174,8 +1175,7 @@
 		g_free(presence->u.chat.user);
 	}
 
-	g_list_foreach(presence->statuses, (GFunc)purple_status_destroy, NULL);
-	g_list_free(presence->statuses);
+	g_list_free_full(presence->statuses, (GDestroyNotify)purple_status_destroy);
 
 	g_hash_table_destroy(presence->status_table);
 
diff --git a/pidgin/gtkblist.c b/pidgin/gtkblist.c
--- a/pidgin/gtkblist.c
+++ b/pidgin/gtkblist.c
@@ -31,6 +31,7 @@
 #include "connection.h"
 #include "core.h"
 #include "debug.h"
+#include "glibcompat.h"
 #include "notify.h"
 #include "prpl.h"
 #include "prefs.h"
@@ -2130,8 +2131,7 @@
 		}
 	}
 
-	g_list_foreach(list, (GFunc)g_free, NULL);
-	g_list_free(list);
+	g_list_free_full(list, (GDestroyNotify)g_free);
 }
 
 static gboolean
diff --git a/pidgin/gtkconv.c b/pidgin/gtkconv.c
--- a/pidgin/gtkconv.c
+++ b/pidgin/gtkconv.c
@@ -219,8 +219,7 @@
 {
 	PidginConversation *gtkconv = data;
 	GList *list = g_list_copy(gtkconv->convs);
-	g_list_foreach(list, (GFunc)purple_conversation_destroy, NULL);
-	g_list_free(list);
+	g_list_free_full(list, (GDestroyNotify)purple_conversation_destroy);
 	return FALSE;
 }
 
@@ -5545,8 +5544,7 @@
 	gtk_object_sink(GTK_OBJECT(gtkconv->tooltips));
 
 	gtkconv->send_history = g_list_first(gtkconv->send_history);
-	g_list_foreach(gtkconv->send_history, (GFunc)g_free, NULL);
-	g_list_free(gtkconv->send_history);
+	g_list_free_full(gtkconv->send_history, (GDestroyNotify)g_free);
 
 	if (gtkconv->attach.timer) {
 		g_source_remove(gtkconv->attach.timer);
diff --git a/pidgin/gtkimhtml.c b/pidgin/gtkimhtml.c
--- a/pidgin/gtkimhtml.c
+++ b/pidgin/gtkimhtml.c
@@ -31,6 +31,7 @@
 #endif
 
 #include "internal.h"
+#include "glibcompat.h"
 #include "pidgin.h"
 #include "pidginstock.h"
 #include "gtkutils.h"
@@ -5692,8 +5693,7 @@
 			if (smiley->imhtml) {
 				if (wids) {
 					GList *children = gtk_container_get_children(GTK_CONTAINER(wids->data));
-					g_list_foreach(children, (GFunc)gtk_widget_destroy, NULL);
-					g_list_free(children);
+					g_list_free_full(children, (GDestroyNotify)gtk_widget_destroy);
 					gtk_container_add(GTK_CONTAINER(wids->data), icon);
 				} else
 					gtk_text_view_add_child_at_anchor(GTK_TEXT_VIEW(smiley->imhtml), icon, anchor);
diff --git a/pidgin/gtklog.c b/pidgin/gtklog.c
--- a/pidgin/gtklog.c
+++ b/pidgin/gtklog.c
@@ -28,6 +28,7 @@
 
 #include "account.h"
 #include "debug.h"
+#include "glibcompat.h"
 #include "log.h"
 #include "notify.h"
 #include "request.h"
@@ -216,8 +217,7 @@
 
 	purple_request_close_with_handle(lv);
 
-	g_list_foreach(lv->logs, (GFunc)purple_log_free, NULL);
-	g_list_free(lv->logs);
+	g_list_free_full(lv->logs, (GDestroyNotify)purple_log_free);
 
 	g_free(lv->search);
 	g_free(lv);
diff --git a/pidgin/gtkmain.c b/pidgin/gtkmain.c
--- a/pidgin/gtkmain.c
+++ b/pidgin/gtkmain.c
@@ -31,6 +31,7 @@
 #include "debug.h"
 #include "eventloop.h"
 #include "ft.h"
+#include "glibcompat.h"
 #include "log.h"
 #include "network.h"
 #include "notify.h"
@@ -287,8 +288,7 @@
 	} else {
 		gtk_window_set_default_icon_list(icons);
 
-		g_list_foreach(icons, (GFunc)g_object_unref, NULL);
-		g_list_free(icons);
+		g_list_free_full(icons, (GDestroyNotify)g_object_unref);
 	}
 #endif
 
diff --git a/pidgin/gtknotify.c b/pidgin/gtknotify.c
--- a/pidgin/gtknotify.c
+++ b/pidgin/gtknotify.c
@@ -31,6 +31,7 @@
 #include "account.h"
 #include "connection.h"
 #include "debug.h"
+#include "glibcompat.h"
 #include "prefs.h"
 #include "pidginstock.h"
 #include "util.h"
@@ -349,8 +350,7 @@
 		gtk_tree_model_get(GTK_TREE_MODEL(pounce_dialog->treemodel), &iter,
 				PIDGIN_POUNCE_DATA, &pounce_data,
 				-1);
-		g_list_foreach(list, (GFunc)gtk_tree_path_free, NULL);
-		g_list_free(list);
+		g_list_free_full(list, (GDestroyNotify)gtk_tree_path_free);
 
 		pounces = purple_pounces_get_all();
 		for (; pounces != NULL; pounces = pounces->next) {
@@ -482,8 +482,7 @@
 
 	button = bd->button;
 	button->callback(purple_account_get_connection(data->account), row, data->user_data);
-	g_list_foreach(row, (GFunc)g_free, NULL);
-	g_list_free(row);
+	g_list_free_full(row, (GDestroyNotify)g_free);
 }
 
 static void *
diff --git a/pidgin/gtksavedstatuses.c b/pidgin/gtksavedstatuses.c
--- a/pidgin/gtksavedstatuses.c
+++ b/pidgin/gtksavedstatuses.c
@@ -27,6 +27,7 @@
 #include "internal.h"
 
 #include "account.h"
+#include "glibcompat.h"
 #include "notify.h"
 #include "request.h"
 #include "savedstatuses.h"
@@ -211,8 +212,7 @@
 		purple_savedstatus_activate(saved_status);
 	}
 
-	g_list_foreach(list, (GFunc)gtk_tree_path_free, NULL);
-	g_list_free(list);
+	g_list_free_full(list, (GDestroyNotify)gtk_tree_path_free);
 }
 
 static void
@@ -249,8 +249,7 @@
 status_window_delete_cancel_cb(gpointer data)
 {
 	GList *sel_titles = data;
-	g_list_foreach(sel_titles, (GFunc) g_free, NULL);
-	g_list_free(sel_titles);
+	g_list_free_full(sel_titles, (GDestroyNotify)g_free);
 }
 
 static void
diff --git a/pidgin/plugins/history.c b/pidgin/plugins/history.c
--- a/pidgin/plugins/history.c
+++ b/pidgin/plugins/history.c
@@ -6,6 +6,7 @@
 
 #include "conversation.h"
 #include "debug.h"
+#include "glibcompat.h"
 #include "log.h"
 #include "notify.h"
 #include "prefs.h"
@@ -150,8 +151,7 @@
 	g_object_ref(G_OBJECT(gtkconv->imhtml));
 	g_idle_add(_scroll_imhtml_to_end, gtkconv->imhtml);
 
-	g_list_foreach(logs, (GFunc)purple_log_free, NULL);
-	g_list_free(logs);
+	g_list_free_full(logs, (GDestroyNotify)purple_log_free);
 }
 
 static void
