Index: epan/emem.c
===================================================================
--- epan/emem.c	(revision 36949)
+++ epan/emem.c	(working copy)
@@ -105,6 +105,12 @@
 #define EMEM_CANARY_SIZE 8
 #define EMEM_CANARY_DATA_SIZE (EMEM_CANARY_SIZE * 2 - 1)
 
+typedef struct _emem_chunk_dtor_t {
+	struct _emem_chunk_dtor_t *next;
+	emem_dtor_cb               dtor;
+	void                      *buf;
+} emem_chunk_dtor_t;
+
 typedef struct _emem_chunk_t {
 	struct _emem_chunk_t *next;
 	char		*buf;
@@ -113,6 +119,8 @@
 	unsigned int	free_offset_init;
 	unsigned int	free_offset;
 	void		*canary_last;
+	/* This points either to emem_dtor_cb or to emem_chunk_dtor_t */
+	void            *dtor;
 } emem_chunk_t;
 
 typedef struct _emem_header_t {
@@ -122,7 +130,7 @@
 	emem_tree_t *trees;		/* only used by se_mem allocator */
 
 	guint8 canary[EMEM_CANARY_DATA_SIZE];
-	void *(*memory_alloc)(size_t size, struct _emem_header_t *);
+	void *(*memory_alloc)(size_t size, struct _emem_header_t *, emem_dtor_cb dtor);
 
 	/*
 	 * Tools like Valgrind and ElectricFence don't work well with memchunks.
@@ -173,8 +181,8 @@
 static intptr_t pagesize;
 #endif /* _WIN32 / USE_GUARD_PAGES */
 
-static void *emem_alloc_chunk(size_t size, emem_header_t *mem);
-static void *emem_alloc_glib(size_t size, emem_header_t *mem);
+static void *emem_alloc_chunk(size_t size, emem_header_t *mem, emem_dtor_cb dtor);
+static void *emem_alloc_glib(size_t size, emem_header_t *mem, emem_dtor_cb dtor);
 
 /*
  * Set a canary value to be placed between memchunks.
@@ -634,6 +642,7 @@
 	npc = g_new(emem_chunk_t, 1);
 	npc->next = NULL;
 	npc->canary_last = NULL;
+	npc->dtor = NULL;
 
 #if defined (_WIN32)
 	/*
@@ -707,20 +716,27 @@
 }
 
 static void *
-emem_alloc_chunk(size_t size, emem_header_t *mem)
+emem_alloc_chunk(size_t size, emem_header_t *mem, emem_dtor_cb dtor)
 {
 	void *buf;
 
 	size_t asize = size;
+	size_t dsize = size;
 	gboolean use_canary = mem->debug_use_canary;
 	guint8 pad;
 	emem_chunk_t *free_list;
 
+	/* Allocate room for destructor's info if needed */
+	if(dtor != NULL) {
+		asize += sizeof(emem_chunk_dtor_t);
+		dsize  = asize;
+	}
+
 	/* Allocate room for at least 8 bytes of canary plus some padding
 	 * so the canary ends on an 8-byte boundary.
 	 * Then add the room needed for the pointer to the next canary.
 	 */
-	 if (use_canary) {
+	if (use_canary) {
 		pad = emem_canary_pad(asize);
 		asize += sizeof(void *);
 	} else
@@ -783,8 +799,16 @@
 	free_list->amount_free -= (unsigned int) asize;
 	free_list->free_offset += (unsigned int) asize;
 
+	if(dtor) {
+		emem_chunk_dtor_t *chunk_dtor = (emem_chunk_dtor_t*)((char*)buf + size);
+		chunk_dtor->dtor = dtor;
+		chunk_dtor->buf  = buf;
+		chunk_dtor->next = (emem_chunk_dtor_t*)free_list->dtor;
+		free_list->dtor  = chunk_dtor;
+	}
+
 	if (use_canary) {
-		char *cptr = (char *)buf + size;
+		char *cptr = (char *)buf + dsize;
 
 		memcpy(cptr, mem->canary, pad-1);
 		cptr[pad-1] = '\0';
@@ -797,13 +821,14 @@
 }
 
 static void *
-emem_alloc_glib(size_t size, emem_header_t *mem)
+emem_alloc_glib(size_t size, emem_header_t *mem, emem_dtor_cb dtor)
 {
 	emem_chunk_t *npc;
 
 	npc=g_new(emem_chunk_t, 1);
 	npc->next=mem->used_list;
 	npc->buf=g_malloc(size);
+	npc->dtor=dtor;
 	npc->canary_last = NULL;
 	mem->used_list=npc;
 	/* There's no padding/alignment involved (from our point of view) when
@@ -816,9 +841,9 @@
 
 /* allocate 'size' amount of memory. */
 static void *
-emem_alloc(size_t size, emem_header_t *mem)
+emem_alloc(size_t size, emem_header_t *mem, emem_dtor_cb dtor)
 {
-	void *buf = mem->memory_alloc(size, mem);
+	void *buf = mem->memory_alloc(size, mem, dtor);
 
 	/*  XXX - this is a waste of time if the allocator function is going to
 	 *  memset this straight back to 0.
@@ -834,31 +859,61 @@
 void *
 ep_alloc(size_t size)
 {
-	return emem_alloc(size, &ep_packet_mem);
+	return emem_alloc(size, &ep_packet_mem, NULL);
 }
 
 /* allocate 'size' amount of memory with an allocation lifetime until the
+ * next packet, call dtor just before lifetime ends.
+ */
+void *
+ep_alloc_dtor(size_t size, emem_dtor_cb dtor)
+{
+	return emem_alloc(size, &ep_packet_mem, dtor);
+}
+
+/* allocate 'size' amount of memory with an allocation lifetime until the
  * next capture.
  */
 void *
 se_alloc(size_t size)
 {
-	return emem_alloc(size, &se_packet_mem);
+	return emem_alloc(size, &se_packet_mem, NULL);
 }
 
+/* allocate 'size' amount of memory with an allocation lifetime until the
+ * next capture, call dtor just before lifetime ends.
+ */
 void *
+se_alloc_dtor(size_t size, emem_dtor_cb dtor)
+{
+	return emem_alloc(size, &se_packet_mem, dtor);
+}
+
+void *
 ep_alloc0(size_t size)
 {
 	return memset(ep_alloc(size),'\0',size);
 }
 
 void *
+ep_alloc_dtor0(size_t size, emem_dtor_cb dtor)
+{
+	return memset(ep_alloc_dtor(size, dtor),'\0',size);
+}
+
+void *
 se_alloc0(size_t size)
 {
 	return memset(se_alloc(size),'\0',size);
 }
 
+void *
+se_alloc_dtor0(size_t size, emem_dtor_cb dtor)
+{
+	return memset(se_alloc_dtor(size, dtor),'\0',size);
+}
 
+
 static gchar *
 emem_strdup(const gchar *src, void *allocator(size_t))
 {
@@ -1119,6 +1174,13 @@
 	npc = mem->free_list;
 	while (npc != NULL) {
 		if (use_chunks) {
+			emem_chunk_dtor_t *dtor = (emem_chunk_dtor_t *)npc->dtor;
+			while (dtor != NULL) {
+				dtor->dtor(dtor->buf);
+				dtor = dtor->next;
+			}
+			npc->dtor = NULL;
+
 			while (npc->canary_last != NULL) {
 				npc->canary_last = emem_canary_next(mem->canary, npc->canary_last, NULL);
 				/* XXX, check if canary_last is inside allocated memory? */
@@ -1137,6 +1199,9 @@
 		} else {
 			emem_chunk_t *next = npc->next;
 
+			if(npc->dtor)
+				((emem_dtor_cb)npc->dtor)(npc->buf);
+
 			emem_scrub_memory(npc->buf, npc->amount_free_init, FALSE);
 
 			g_free(npc->buf);
Index: epan/emem.h
===================================================================
--- epan/emem.h	(revision 36949)
+++ epan/emem.h	(working copy)
@@ -36,6 +36,10 @@
  */
 void emem_init(void);
 
+/** Destructor callback. Called when the memory chunk previously allocated in
+ * one of the pools is about to be collected. The supplied argument is the chunk it self */
+typedef void (*emem_dtor_cb)(void *chunk);
+
 /* Functions for handling memory allocation and garbage collection with
  * a packet lifetime scope.
  * These functions are used to allocate memory that will only remain persistent
@@ -56,6 +60,16 @@
 void* ep_alloc0(size_t size) G_GNUC_MALLOC;
 #define ep_new0(type) ((type*)ep_alloc0(sizeof(type)))
 
+/** Allocate memory with a packet lifetime scope and call dtor before memory is
+ * deallocated
+ */
+void *ep_alloc_dtor(size_t size, emem_dtor_cb dtor) G_GNUC_MALLOC;
+
+/** Allocate memory with a packet lifetime scope, fill it with zeros and call dtor
+ * before memory is deallocated
+ */
+void *ep_alloc_dtor0(size_t size, emem_dtor_cb dtor) G_GNUC_MALLOC;
+
 /** Duplicate a string with a packet lifetime scope */
 gchar* ep_strdup(const gchar* src) G_GNUC_MALLOC;
 
@@ -76,10 +90,20 @@
 #define ep_alloc_array(type,num) (type*)ep_alloc(sizeof(type)*(num))
 
 /** allocates with a packet lifetime scope an array of type made of num elements,
- * initialised to zero.
+ * initialised to zero
  */
 #define ep_alloc_array0(type,num) (type*)ep_alloc0(sizeof(type)*(num))
 
+/** allocates with a packet lifetime scope an array of type made of num elements
+ *  and dtor is called before memory is deallocated
+ */
+#define ep_alloc_array_dtor(type,num,dtor) (type*)ep_alloc_dtor(sizeof(type)*(num),dtor)
+
+/** allocates with a packet lifetime scope an array of type made of num elements,
+ * initialised to zero, and dtor is called before memory is deallocated
+ */
+#define ep_alloc_array_dtor0(type,num,dtor) (type*)ep_alloc_dtor0(sizeof(type)*(num),dtor)
+
 /**
  * Splits a string into a maximum of max_tokens pieces, using the given
  * delimiter. If max_tokens is reached, the remainder of string is appended
@@ -141,6 +165,16 @@
 /** Allocate memory with a capture lifetime scope and fill it with zeros*/
 void* se_alloc0(size_t size) G_GNUC_MALLOC;
 
+/** Allocate memory with a capture lifetime scope and call dtor before memory is
+ * deallocated
+ */
+void *se_alloc_dtor(size_t size, emem_dtor_cb dtor) G_GNUC_MALLOC;
+
+/** Allocate memory with a capture lifetime scope, fill it with zeros and call dtor
+ * before memory is deallocated
+ */
+void* se_alloc_dtor0(size_t size, emem_dtor_cb dtor) G_GNUC_MALLOC;
+
 /** Duplicate a string with a capture lifetime scope */
 gchar* se_strdup(const gchar* src) G_GNUC_MALLOC;
 
@@ -158,7 +192,12 @@
 /** allocates with a capture lifetime scope an array of type made of num elements */
 #define se_alloc_array(type,num) (type*)se_alloc(sizeof(type)*(num))
 
-/** release all memory allocated */
+/** allocates with a capture lifetime scope an array of type made of num elements
+ * and dtor is called before memory is deallocated
+ */
+#define se_alloc_array_dtor(type,num,dtor) (type*)se_alloc(sizeof(type)*(num),dtor)
+
+/** release all memory allocated and call destructors before release occurs */
 void se_free_all(void);
 
 
Index: epan/libwireshark.def
===================================================================
--- epan/libwireshark.def	(revision 36949)
+++ epan/libwireshark.def	(working copy)
@@ -367,6 +367,8 @@
 ep_address_to_str
 ep_alloc
 ep_alloc0
+ep_alloc_dtor
+ep_alloc_dtor0
 ep_free_all
 ep_memdup
 ep_stack_new
@@ -934,6 +936,8 @@
 scsi_ssc_vals                                   DATA
 se_alloc
 se_alloc0
+se_alloc_dtor
+se_alloc_dtor0
 se_memdup
 se_strdup
 se_strdup_printf
