我的结构数组在C#中耗尽内存我该如何修复它?

时间:2016-01-17 21:28:06

标签: c# .net memory data-structures collections

你好我必须将这个结构的所有元素存储在内存中进行处理,我不能一次加载它的块我必须在任何时候加载它所以我试图将它全部装入内存以某种方式耗尽内存,即使我有大约20 GB的RAM,也许还有17 GB。我知道Collisions的内部限制为2 GB,所以RAM在这个意义上并不重要。

以下是我的布局如何

public struct REGTYPE
{
    public byte REG_Kind; // ;1=8 bits \ 2=16 bits \ 3=32 bits \ 4=MMX \ 5=XMM \ 6=Float stack \ 7=Segment \ 8=Debug \ 9=Control \ 10=Test
    public byte REG_Ptr_Kind; // ;1=Byte PTR \ 2=Word PTR \ 3=Dword PTR \ 4=Qword PTR \ 5=mmword ptr \ 6=xmmword ptr \ 7=FWord PTR \ 8=tbyte ptr \ 9=null ptr (LEA)
    public byte REG_Type; //  ;0-7= direct register index \ 16 register=byte && 7 \ 32 register=(byte && 63)/8 \ 64=[32/16 address only] \ 128=[using x86 relatives]
    public byte REG_BaseAsReg; // ? ;1=Register only (BASE exposed)!
}

public struct REGSTRUCT
{
    public uint SEG_TYPE;
    public uint Base;
    public uint INDEX;
    public uint SCALE;
    public uint DISPLACEMENTS;
    public uint DISPLACEMENT_TYPE;
    public REGTYPE REG_Kind;
    public uint PTR_TYPE;
}

public struct IMMSTRUCT
{
    public uint VALUE_LO;
    public uint VALUE_HI;
    public uint VALUE_TYPE; //     1=Byte \ 2=Word \ 4=Dword \ 8=ByteToWord \ 16=ByteToDword \ 32=AbsJump \ 64=ShortJump \ 128=LongJump
}


public struct DisAsmStruct
{
    public uint Instruction_Prefix;
    public uint Instruction;
    public REGSTRUCT Reg1;
    public REGSTRUCT Reg2;
    public uint Reg_Reg; //1=from ptr
    public IMMSTRUCT Imm;
    public uint Instruction_Length;
}

public struct AsmStruct
{
    public uint Address;
    public string ASM;
    public DisAsmStruct disASM; //tried to add ref keyword no success
}

public static AsmStruct[] AsmCache = null;

在运行此代码的过程中,它会在Array.Resize行崩溃,说明当AshCache达到大约200万个元素时它会耗尽内存,它必须在它之前达到10个可能的2000万个元素完成加载,我知道可以将所有这些包装在结构中,而不会像在C ++中那样耗尽内存,我也相信我知道这个问题的原因,原因是它将结构存储为它本身的副本而不仅仅是对该结构的引用,因此每个结构浪费了两倍的内存,如何在AsmCache中通过引用存储结构?我使用Array.Resize的原因是每次发现更多指令时将收集限制增加1000.我不会设置限制到某个任意限制。这就是我以前在Vb6(ReDim Preserve)中使用它的方法

DisAsmStruct DisA = new DisAsmStruct();
AsmCache = new AsmStruct[1001];
Array.Resize(ref AsmCache, AsmCache.GetUpperBound(0) + 1001);
AsmCache[Number + 1].Address = BaseAddress + CNT;
AsmCache[Number + 1].disASM = ref DisA; //this line will error as I tried to fix it (remove ref to work)
AsmCache[Number + 1].ASM = OpCode; //Like "MOV EAX, [ECX+34h]" blah blah

2 个答案:

答案 0 :(得分:1)

如果要允许大于2GB的对象,则需要允许它们。 下面将根据您的项目类型进入您的app.config文件或其他配置文件。

<configuration>
    <runtime>
        <gcAllowVeryLargeObjects enabled="true" />
    </runtime>
</configuration>

<强>文档

https://msdn.microsoft.com/en-us/library/hh285054(v=vs.110).aspx

答案 1 :(得分:1)

使AsmStruct成为一个类,否则当你调整数组大小时(或List调整自身大小)你将所有数据复制到新位置(这是非常慢的顺便说一句)。使用AsmStruct作为类只复制指针。我模拟了你的调整大小策略和课程你可以在OutOfMemory之前创建4倍以上的项目。

使用editbin技巧.NET Out Of Memory Exception - Used 1.3GB but have 16GB installed您可以将限制推高2倍。

如果这还不够,并且您只有32位库,则必须以某种方式拆分程序。一个32位程序与库通信,一个64位处理。