C#List <string>未收集内存

时间:2015-12-11 22:27:28

标签: c# memory-leaks

此代码分配内存,但永远不会释放内存。如何强制收集内存,GC.Collect()似乎也不起作用。

我已经回顾了许多提出这个问题的帖子,但每个人都回答说垃圾收集器会处理内存,但它永远不会。

    var list = new List<string>();

    for (var i = 0; i < 10000000; i++)
    {
      list.Add("really long string..................................................................................................");
    }

    for (var i = 0; i < 10000000; i++)
    {
      list[i] = null;
    }

    list.Clear();

2 个答案:

答案 0 :(得分:3)

这是code of List<T>.Clear

// Clears the contents of List.
public void Clear() {
    if (_size > 0)
    {
        Array.Clear(_items, 0, _size); // Don't need to doc this but we clear the elements so that the gc can reclaim the references.
        _size = 0;
    }
    _version++;
}

如您所见,数组按原样保持分配状态。这是出于效率原因而完成的。数组已经分配,​​没有必要让GC收集它,因为它可能会再次需要。

您可以设置Capacity属性以强制它重新分配新数组。这实际上会添加内存压力(除非你将其设置为0),直到收集到前一个数组。这是code for reference

// Gets and sets the capacity of this list.  The capacity is the size of
// the internal array used to hold items.  When set, the internal 
// array of the list is reallocated to the given capacity.
// 
public int Capacity {
    get {
        Contract.Ensures(Contract.Result<int>() >= 0);
        return _items.Length;
    }
    set {
        if (value < _size) {
            ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.value, ExceptionResource.ArgumentOutOfRange_SmallCapacity);
        }
        Contract.EndContractBlock();

        if (value != _items.Length) {
            if (value > 0) {
                T[] newItems = new T[value];
                if (_size > 0) {
                    Array.Copy(_items, 0, newItems, 0, _size);
                }
                _items = newItems;
            }
            else {
                _items = _emptyArray;
            }
        }
    }
}

至于你的非常长的字符串,它只是对一个实习字符串的引用......无论如何,该列表将存储每个项目8个字节(假设一个64位系统)。

答案 1 :(得分:-2)

如果您明确致电GC.Collect(),并不意味着它会立即被收集。 GC将决定何时收集......