none
C# Hashtable GetEnumerator bugs?

    Question

  • There is part of my server code:

    IDictionaryEnumerator enumerator = GetHashtable(userlist).GetEnumerator(); while (enumerator.MoveNext()) { DictionaryEntry current = (DictionaryEntry)enumerator.Current; try { GClient client = (GClient)current.Value; Console.WriteLine("Money: " + client.money); } catch (Exception ex) { Console.WriteLine(ex); } }

    public static Hashtable GetHashtable(Hashtable ht)
    {
    return (Hashtable)ht.Clone();
    }

    After the code is executed many times(More than 10000), the ANTS Memory Profiler shown that the hashtable+bucket are leaked, Many of userlist enumerator were added and haven't been collected, Also, the server started being laggy and 

    having lots of NullReferenceException from this code

    Does anyone know the problem?


    • Edited by 6387534 Friday, June 28, 2013 10:29 AM
    Friday, June 28, 2013 10:29 AM

All replies

  • "having lots of NullReferenceException from this code"

    Where in the code?

    The only thing I can think of is that you're modifying the hashtable from other threads and you end up with a corrupted hashtable. Though it's hard to explain the "memory leak", there's nothing in this code that could cause leaks.

    Saturday, June 29, 2013 6:43 AM
  • Will it corrupt the table if having exception? (I write in other code)

    (Notice: I haven't break the enumerator while having exception)

    There is my ANTS log:


    • Edited by 6387534 Monday, July 01, 2013 7:30 AM Edit
    Monday, July 01, 2013 7:29 AM
  • "Will it corrupt the table if having exception? (I write in other code)"

    Maybe though I don't remember such a case. Anyway, I don't see any other explanation for a NullReferenceException in that code.

    "There is my ANTS log"

    I don't see how you conclude you have a leak from that log. You have 2875 bucket arrays, so what? You say that the code is execute many times and every time the code is executed it clones the Hashtable. No wonder there are many bucket arrays.

    Monday, July 01, 2013 7:46 AM
  • Thanks for reply,

    Actually when i had run the code by 5000 times(just a sample), the hashtable+bucket of memory usage were not huge increased,

    but while it runs after 10000 times or more(also a sample), it would huge increased

    As you can see from image, the memory usage were being increased from a period of time.


    • Edited by 6387534 Monday, July 01, 2013 7:57 AM edited
    Monday, July 01, 2013 7:53 AM
  • That doesn't prove anything. The only way to "leak" a managed object is to have references to it that shouldn't be there. Like storing the enumerators or the cloned hashtables in a static ArrayList. There's nothing like this in your example.

    Monday, July 01, 2013 8:55 AM
  • I would guess that the NullReferenceException is caused by attempting to reference a Null (brilliant!).  The obvious thing is that current.Value is sometimes null.

    If you comment out

    Console.WriteLine("Money: " + client.money);

    do the NullReferenceExceptions go away?

    At least do

    if (client != null) Console.WriteLine("Money: " + client.money);


    Paul Linton

    Monday, July 01, 2013 9:27 AM
  • Ok, NullReferenceExceptions is fixed, but  i am still in stuck of the memory leaking...

    I found that my hashtable enumerator seems being leaked while the table are bugged from the other code.

    but i cant find where the problem it is:( 

    Wednesday, July 03, 2013 9:15 AM
  • What does "seems being leaked" mean?  Just because your application uses more memory over time does not mean that you have a memory leak.  If the system is not under memory pressure there may be no need for the garbage collector to run for a long period of time (days, maybe) and so your observed memory usage would go up.  So what?

    I am not saying you don't have a memory leak, just that using more memory over time does not necessarily mean a memory leak.  It may just be a sign of being efficient!

    What is GClient?  Does it allocate non-managed resources?  Does it always release them?


    Paul Linton

    Wednesday, July 03, 2013 9:57 AM
  • GClient is a class made by me.

    After a long test, i found the Hashtable GetEnumerator were able to free the memory on the first time the server loaded for random hours, but the enumerator suddenly leaked at the time client count is increased, i can see the ANTS profiler shows hashtable+buckets is leaked. (I think there is something make ClientList get into error)

    How can i force the enumerator to be collected after a loop is finished?

    Notice: I have a lot of enumerator used in the server program. 
    Edit: I have also added GC.Collect() in client disconnect.
    • Edited by 6387534 Friday, July 05, 2013 6:25 PM edit2
    Friday, July 05, 2013 4:05 PM
  • "How can i force the enumerator to be collected after a loop is finished?"

    You can't force the GC to collect the enumerator (or any other object) after the loop (or any other point of the program). Well, you can add GC.Collect but will likely lead to performance problems and it's not recommended.

    I still don't understand why you claim you have a leak. It's more likely that you do not understand how GC works. The GC doesn't collect objects as soon as they are no longer referenced, it collects objects when memory is allocated and the currently available free memory is not enough. And when the GC does collect object it doesn't collect all unreferenced objects, it collects objects up to a generation (0 gen collection happen often, 2nd generation collections happen rarely).

    So, simply saying that you have 2000 bucket arrays in memory is meaningless. Maybe the GC didn't yet collect them. You have a problem if the application memory usage increases without bounds and you end up with an OutOfMemoryException. But you haven't told us anything about that.

    Monday, July 08, 2013 3:16 PM