ConditionalWeakTable.GetOrCreateValue()中的IndexOutOfRangeException

时间:2017-07-19 21:21:50

标签: c# .net

我使用ConditionalWeakTable作为弱事件处理程序实现的一部分。它工作正常,除了偶尔我收到来自我的用户的自动崩溃日志,表明对GetOrCreateValue()的调用已崩溃。

错误和调用堆栈看起来像下面两个堆栈之一,我假设取决于是否存在现有条目或需要创建新条目:

System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at System.Runtime.CompilerServices.ConditionalWeakTable`2.CreateEntry(TKey key, TValue value)
   at System.Runtime.CompilerServices.ConditionalWeakTable`2.GetValue(TKey key, CreateValueCallback createValueCallback)
   at [my code]

System.IndexOutOfRangeException: Index was outside the bounds of the array.
   at System.Runtime.CompilerServices.ConditionalWeakTable`2.FindEntry(TKey key)
   at System.Runtime.CompilerServices.ConditionalWeakTable`2.TryGetValueWorker(TKey key, TValue& value)
   at System.Runtime.CompilerServices.ConditionalWeakTable`2.TryGetValue(TKey key, TValue& value)
   at System.Runtime.CompilerServices.ConditionalWeakTable`2.GetValue(TKey key, CreateValueCallback createValueCallback)
   at [my code]

(对GetOrCreateValue()的实际调用似乎已经内联。)

这是我的代码,声明了ConditionalWeakTable

private static readonly ConditionalWeakTable<object, Dictionary<EventInfo, object>> s_sourceObjects = new ConditionalWeakTable<object, Dictionary<EventInfo, object>>();

这是我调用GetOrCreateValue()的代码:

Dictionary<EventInfo, object> events;
lock(s_sourceObjects)
    events = s_sourceObjects.GetOrCreateValue(sourceObject);

这是引用s_sourceObjects字段的唯一其他地方:

bool success;
Dictionary<EventInfo, object> events;
lock(s_sourceObjects)
    success = s_sourceObjects.TryGetValue(sourceObject, out events);

(我添加了lock语句,因为我怀疑ConditionalWeakTable中存在线程安全错误,尽管文档声称它是线程安全的。但是,即使使用了lock语句,显然它不是线程问题。)

我的应用程序使用.NET 4.6.2。

我是否误解或不理解ConditionalWeakTable?或者这是一个框架错误?如果它是一个框架错误,我有什么方法可以解决它吗?

如果有人想查看上下文,请参阅此类的完整源代码:https://gist.github.com/waltdestler/2a339bdd0d7d647501eb4690772e3b50

1 个答案:

答案 0 :(得分:0)

万一其他人遇到这个问题,我想跟进原因是什么:

我的程序实际上是一个视频游戏,事实证明有些玩家正在使用一个名为Cheat Engine的工具,它可以用来直接修改内存值。 (例如,改变记录玩家拥有多少钱的内存。)我发现Cheat Engine在发生此类崩溃时正在运行,这让我相信玩家正试图用它来欺骗游戏并且无意中编辑了错误的内存位置并导致其崩溃。