Thread: Dynamic memory and realloc(), freeing memory

  1. #1
    Grey Wizard C_Sparky's Avatar
    Join Date
    Sep 2009
    Posts
    50

    Dynamic memory and realloc(), freeing memory

    I've made a registry editor with a treeview for the keys and a listview for the values.

    I use a global pointer to a structure to hold the list of values:
    Code:
    // in registry.h
    struct value_t{
        char name[MAX_VALUE];
        DWORD type;
        char* data;
    };
    Code:
    // in registry.c
    struct value_t *g_values;
    When a key is loaded, a function finds the total number of values, and allocates memory for the global structure like so:
    Code:
    memset(g_values, 0, sizeof(g_values));
    g_values = (struct value_t*)realloc(g_values,
                                                (data.cValues + 32) * sizeof(struct value_t) + sizeof(struct value_t));
    
    // fill structure members...
    // the char* data member is reallocated in a similar way as above
    I loaded task manager to watch the amount of memory consumption.
    With each click of a different registry key, realloc() is called with the global structure and memory is allocated for the number of values in that key.

    I would expect the memory to reduce if I load a key with less or no values, since realloc() calls free(). But when loading a blank key, the memory remains the same, and then upon loading a key with many values, the memory increases, and keeps increasing, eventually reaching a ridiculous amount.

    Why is the memory not being free'd? Or is task manager a unreliable tool to monitor dynamic memory?


    Edit:
    After carefully re-reading this http://www.cplusplus.com/reference/c...tdlib/realloc/,
    I found that calling memset(&g_values, 0, sizeof(g_values)) was making it a NULL pointer, and thus realloc() was allocating a new block each time. My mistake.
    Last edited by C_Sparky; 10-02-2010 at 05:38 PM.

  2. #2
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Why would you load a separate struct with registry values when the treeview and listview themselves also hold the same information?

  3. #3
    Grey Wizard C_Sparky's Avatar
    Join Date
    Sep 2009
    Posts
    50
    Not sure if I'm on the same page as you, but the treeview holds one value for each item(key name), which is stored in the treeview control. And the listview has 3 columns in which a global structure is required to maintain the data.

  4. #4
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Quote Originally Posted by C_Sparky View Post
    Not sure if I'm on the same page as you,
    Maybe not...

    but the treeview holds one value for each item(key name), which is stored in the treeview control. And the listview has 3 columns in which a global structure is required to maintain the data.
    Not especially... if you're doing anything like the standard REGEDIT, that's all held in the listview control itself.

    I'm not saying your application doesn't need this... it's just that with controls like treeview and listview doing their own internal memory management, it hardly seems necessary for most uses. That's kinda the point... let the controls do it for you.

    The only exception might be REG_BINARY values in which case you can use the listview's LPARAM for each item to store a pointer to the data... and the list view will still manage it for you.

    Strings can be stored right in the listview column. Dwords in the LPARAM itself with a string representation in the collumn...

    Don't forget, some of those keys have a lot of values under them... HKEY_CLASSES_ROOT has literally thousands of them. That's a lot of duplication if you store it in a control and on the heap.

    Further if you think about it... the treeview indexes your Keys... the listview indexes values under each key. The only value or key you actually care about is the one that's currently selected...

    Anyway... I just thought I'd chime in, thinking that perhaps you hadn't thought about this approach. I do a fair bit of WinAPI programming and whenever possible I let the controls do the work for me...

  5. #5
    Grey Wizard C_Sparky's Avatar
    Join Date
    Sep 2009
    Posts
    50
    I do have it set up to when the user clicks on a treeview item, it goes up the parent nodes to the root node and gets the full key path, then calls a separate function to enumerate the values in the key and add them to the listview(accessing the global struct). So it's not indexing the values under every single key.

    I have it recursively enumerating the entire registry however, excluding HKEY_CLASSES_ROOT for now, it usually holds about an extra 27 MB in memory for the treeview.

    This is actually my first time using listviews, and treeviews for that matter. I'm not completely comfortable with how listviews work quite yet. Your logic is sound regarding storing a pointer to data through the LPARAM of the listview. But how would I implement this without the use of global or static variables? Since the actual modification of the listview is happening in a separate function.

    Thanks for your insight.

    Edit: This registry editor is a small part of an application I'm developing for system repair and management. It needs to be 100% portable, here is the sourceforge project: http://sourceforge.net/projects/mastercontrol/
    Last edited by C_Sparky; 10-04-2010 at 08:52 PM.

  6. #6
    Banned
    Join Date
    Aug 2010
    Location
    Ontario Canada
    Posts
    9,547
    Ok think about what you've got...

    First you don't need to load the entire treeview at one time.
    You only need to load the branches that are OPEN.
    For this you can use the treeview's "expanding" notification to enumerate sub keys and place their names in the list. When the branch is closed you can use the "closing" notification to free up that memory by deleting it's children.

    Indexing the full path is simple... just walk up the open branch building a path from the key names in the treeview until you hit the root.

    For the list view you don't need to hold all that data in memory. What you do when showing values under a key is to enumerate the values, stuff them into the listview one at a time and forget them.
    When the user clicks on a value in the list, you open it all by itself in a dialog. When he closes the dialog, dump the memory and get back to maintaining your list and tree.

    These things can be very efficient, memory wise, which is why my choice has always been to let the controls manage the data for me. All I ever open is the one item I need...

    I do hope this is helpful for you. What I'm suggesting is that you spend a bit of time and figure out how to do this in the smallest memory footprint possible...

  7. #7
    Grey Wizard C_Sparky's Avatar
    Join Date
    Sep 2009
    Posts
    50
    I'm really glad you brought this up. I am rewriting my functions to use the listviews(I have several for other parts of the program) to be used without global structures.

    I'm still working on getting the TVN_EXPANDING notification to work for me, if I still don't have any luck I'll post something in the Windows section, but it'll just take some time as always.

    Thanks for your time, I'll be sure to come back to you if I have any more questions regarding things like this.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Problem with custom dynamic memory allocation routines
    By BLauritson in forum C++ Programming
    Replies: 12
    Last Post: 03-11-2010, 07:26 AM
  2. call to realloc() inside a function: memory problem
    By simone.marras in forum C Programming
    Replies: 15
    Last Post: 11-30-2008, 10:01 AM
  3. Issues with free and dynamic memory
    By dan s in forum C Programming
    Replies: 3
    Last Post: 01-14-2007, 03:44 AM
  4. using realloc
    By bobthebullet990 in forum C Programming
    Replies: 14
    Last Post: 12-06-2005, 05:00 PM
  5. Using realloc to make memory smaller?
    By electrolove in forum C Programming
    Replies: 6
    Last Post: 02-06-2003, 10:00 AM