---
Hi,

This code is mainly for debugging. I don't expect it to be applied, but don't object if it is.

It exposes a number of memory leaks in richedit. For example, running the richedit regression test shows leaks at:

 line 248 file editor.c
 line 1120 file editor.c
 line 2230 file editor.c
 line 355 file string.c
 line 82 file undo.c
 line 2342 file reader.c
 line 2240 file editor.c
 line 32 file string.c
 line 35 file string.c
 line 145 file list.c

etc.

To use it, simply apply the attached patch, and run your favourite program that uses the richedit control. (Assumes you have the previous two patches I sent to wine-patches applied.)

Mike


 dlls/riched20/editor.c |   33 +++++++++++++++++++
dlls/riched20/editor.h | 84 ++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 117 insertions(+), 0 deletions(-)
diff --git a/dlls/riched20/editor.c b/dlls/riched20/editor.c
index 93aed91..c8844d2 100644
--- a/dlls/riched20/editor.c
+++ b/dlls/riched20/editor.c
@@ -1236,6 +1236,37 @@ static const WCHAR wszClassName50[] = {'
 static const WCHAR wszClassNameListBox[] = {'R','E','L','i','s','t','B','o','x','2','0','W', 0};
 static const WCHAR wszClassNameComboBox[] = {'R','E','C','o','m','b','o','B','o','x','2','0','W', 0};
 
+struct list memory_list;
+CRITICAL_SECTION mem_cs;
+
+CRITICAL_SECTION mem_cs;
+static CRITICAL_SECTION_DEBUG mem_cs_debug =
+{
+    0, 0, &mem_cs,
+    { &mem_cs_debug.ProcessLocksList,
+      &mem_cs_debug.ProcessLocksList },
+      0, 0, { (DWORD_PTR)(__FILE__ ": mem_cs") }
+};
+CRITICAL_SECTION mem_cs = { &mem_cs_debug, -1, 0, 0, 0, 0 };
+
+static void dump_allocated_memory(void)
+{
+    struct mem_list *mem;
+    int size = 0, count = 0;
+
+    EnterCriticalSection( &mem_cs );
+    LIST_FOR_EACH_ENTRY( mem, &memory_list, struct mem_list, entry )
+    {
+        ERR("unfreed memory %p line %d file %s\n", mem, mem->line, mem->file);
+        size += HeapSize( GetProcessHeap(), 0, mem );
+        size -= sizeof (*mem);
+        count++;
+    }
+    LeaveCriticalSection( &mem_cs );
+    if( count )
+        ERR("%d unfreed chunks %d bytes\n", count, size);
+}
+
 BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
 {
     TRACE("\n");
@@ -1243,6 +1274,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, 
     {
     case DLL_PROCESS_ATTACH:
       DisableThreadLibraryCalls(hinstDLL);
+      list_init( &memory_list );
       me_heap = HeapCreate (0, 0x10000, 0);
       ME_RegisterEditorClass(hinstDLL);
       break;
@@ -1256,6 +1288,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, 
           UnregisterClassW(wszClassNameListBox, 0);
       if (ME_ComboBoxRegistered)
           UnregisterClassW(wszClassNameComboBox, 0);
+      dump_allocated_memory();
       HeapDestroy (me_heap);
       me_heap = NULL;
       break;
diff --git a/dlls/riched20/editor.h b/dlls/riched20/editor.h
index 87742c5..38c6021 100644
--- a/dlls/riched20/editor.h
+++ b/dlls/riched20/editor.h
@@ -20,9 +20,15 @@
 
 #include "editstr.h"
 #include "wine/unicode.h"
+#include "wine/debug.h"
+#include "wine/list.h"
 
 extern HANDLE me_heap;
 
+#define MEM_DEBUG
+
+#ifndef MEM_DEBUG
+
 static inline void *richedit_alloc( size_t len )
 {
     return HeapAlloc( me_heap, 0, len );
@@ -38,6 +44,84 @@ static inline void *richedit_realloc( vo
     return HeapReAlloc( me_heap, 0, ptr, len );
 }
 
+#else
+
+extern struct list memory_list;
+extern CRITICAL_SECTION mem_cs;
+
+#define MSI_MEM_MAGIC 0x04250919
+
+struct mem_list {
+    int magic;
+    struct list entry;
+    int line;
+    const char *file;
+};
+
+static inline void *__richedit_alloc( int flags, size_t len, int line, const char *file )
+{
+    struct mem_list *elem;
+    EnterCriticalSection( &mem_cs );
+    elem = HeapAlloc( GetProcessHeap(), flags, sizeof *elem + len );
+    if (elem)
+    {
+        elem->magic = MSI_MEM_MAGIC;
+        elem->line = line;
+        elem->file = file;
+        list_add_tail( &memory_list, &elem->entry );
+        elem++;
+    }
+    LeaveCriticalSection( &mem_cs );
+    return elem;
+}
+
+static inline void *__richedit_realloc( void *mem, int flags, size_t len, int line, const char *file )
+{
+    struct mem_list *elem = mem;
+    if (!elem--) return NULL;
+
+    if (elem->magic != MSI_MEM_MAGIC)
+    {
+        MESSAGE("richedit: bad realloc %s # %d\n", file, line);
+        return NULL;
+    }
+    EnterCriticalSection( &mem_cs );
+    list_remove( &elem->entry );
+    elem = HeapReAlloc( GetProcessHeap(), flags, elem, sizeof *elem + len );
+    if (elem)
+    {
+        list_add_tail( &memory_list, &elem->entry );
+        elem++;
+    }
+    LeaveCriticalSection( &mem_cs );
+
+    return elem;
+}
+
+static inline BOOL __richedit_free( void *mem, int line, const char *file )
+{
+    struct mem_list *elem = mem;
+    if (!elem--) return TRUE;
+    if (elem->magic != MSI_MEM_MAGIC)
+    {
+        MESSAGE("richedit: bad free (%p) %s # %d\n", mem, file, line);
+        (*(int*)0) = 0;
+        return FALSE;
+    }
+    elem->magic = 0;
+    EnterCriticalSection( &mem_cs );
+    list_remove( &elem->entry );
+    LeaveCriticalSection( &mem_cs );
+    return HeapFree( GetProcessHeap(), 0, elem );
+}
+
+#define richedit_alloc( len ) __richedit_alloc( 0, len, __LINE__, __FILE__ )
+#define richedit_realloc( mem, len ) __richedit_realloc( mem, 0, len, __LINE__, __FILE__ )
+#define richedit_free( mem ) __richedit_free( mem, __LINE__, __FILE__ )
+
+#endif
+
+
 #define ALLOC_OBJ(type) richedit_alloc(sizeof(type))
 #define ALLOC_N_OBJ(type, count) richedit_alloc((count)*sizeof(type))
 #define FREE_OBJ(ptr) richedit_free(ptr)



Reply via email to