C# 编译器 (csc.exe) 内存溢出编译嵌套的类型和 Linq

发布时间: 2017/2/28 21:10:55
注意事项: 本文中文内容可能为机器翻译,如要查看英文原文请点击上面连接.

我发现一个不愉快的行为与 Visual Studio 一起发展。在编译 C# 时,它就挂我的机器。

已经沦为下一个最小的源代码的行为

using System.Collections.Generic;
using System.Linq;

namespace memoryOverflowCsharpCompiler {

    class SomeType { public decimal x; }

    class TypeWrapper : Dictionary<int,
                        Dictionary<int,
                        Dictionary<int, SomeType [] []>>> {

        public decimal minimumX() {
            return base.Values.Min(a =>
                      a.Values.Min(b =>
                      b.Values.Min(c =>
                      c       .Sum(d =>
                      d       .Sum(e => e.x)))));
        }
    }
}

使用编译

PROMPT> csc source.cs

    *** BANG! overflow memory usage (up to ~3G)

PROMPT> csc /?
Microsoft (R) Visual C# Compiler version 12.0.30501.0
Copyright (C) Microsoft Corporation. All rights reserved.
...

(使用 Windows 8.1 临 N x64; csc与 32 位运行编译器进程)

悦目的修改不能产生这种行为 (如。 改变 decimalint ,减少一个嵌套的级别......),执行大 Select 然后减少,工作正常

明确的解决方法︰

            return base.Values.SelectMany(a =>
                      a.Values.SelectMany(b =>
                      b.Values.Select    (c =>
                      c.       Sum       (d =>
                      d.       Sum       (e => e.x))))).Min();

虽然此显式的变通方法存在,它不能保证不会再次发生这种行为。

怎么了?

谢谢!

解决方法 1:

它似乎泛型类型解析失败在这种情况下。改变从 decimalint 偶然工作。如果你增加嵌套级别,比你可以看到,它也没有为 int。对我 x64 本机代码编译为两个 intdecimal 和使用大约 2.5 GB 的内存,但增加嵌套级别结果在溢出时增长到伴 4 GB 的内存使用情况。

显式地指定类型参数允许编译的代码︰

class TypeWrapper : Dictionary<int, Dictionary<int, Dictionary<int, Dictionary<int, SomeType[][]>>>>
{
    public decimal minimumX()
    {
        return base.Values
            .Min<Dictionary<int, Dictionary<int, Dictionary<int, SomeType[][]>>>, decimal>(a => a.Values
                .Min<Dictionary<int, Dictionary<int, SomeType[][]>>, decimal>(b => b.Values
                    .Min<Dictionary<int, SomeType[][]>, decimal>(c => c.Values
                        .Min(d => d
                            .Sum(e => e.Sum(f => f.x))
                        )
                    )
                )
            );
    }
}

此外编译器的工作当你通过引入本地变量减少嵌套︰

class TypeWrapper : Dictionary<int, Dictionary<int, Dictionary<int, Dictionary<int, SomeType[][]>>>>
{
    public decimal minimumX()
    {
        Func<Dictionary<int, SomeType[][]>, decimal> inner = (Dictionary<int, SomeType[][]> c) => c.Values
                        .Min(d => d
                            .Sum(e => e.Sum(f => f.x))
                        );

        return base.Values
            .Min(a => a.Values
                .Min(b => b.Values
                    .Min(inner)
                )
            );
    }
}
官方微信
官方QQ群
31647020