c# - List.Contains 上的索引越界

标签 c#

我正在使用的 CMS (DNN) 中的一段代码抛出以下异常:

“索引超出了数组的范围。”

随着堆栈跟踪说:

 at System.Collections.Generic.List`1.Contains(T item)

这个问题只是偶尔发生(我怀疑它与缓存损坏有关)并且只在生产中发生。这意味着我无法始终如一地重现它。我最感兴趣的是它是如何发生的。

调用“包含”怎么可能触发索引越界?

额外信息

调用 Contains 的代码按以下方式工作(我简化了代码以使重要部分更具可读性。链接指向确切的类和行号)

CustomUrlDictController.cs

 List<int> urlPortals;
 var cc = new CacheController();
 cc.GetFriendlyUrlIndexFromCache(out urlPortals);
 var boolean = urlPortals.Contains(portalId); // This is where the exception happens.

CacheController.cs

void GetFriendlyUrlIndexFromCache(out List<int> urlPortals)
{
    urlPortals = null;
    object rawPortals = DataCache.GetCache(UrlPortalsKey);
    if (rawPortals != null)
    {
        urlPortals = (List<int>)rawPortals;
    }
}

数据缓存(12)

object GetCache(string CacheKey)
{
    return Cache[cacheKey];
}

完整堆栈跟踪

InnerMessage:Index was outside the bounds of the array.
InnerStackTrace:
at System.Collections.Generic.List`1.Contains(T item)
   at DotNetNuke.Entities.Urls.CustomUrlDictController.FetchCustomUrlDictionary(Int32 portalId, Boolean forceRebuild, Boolean bypassCache, FriendlyUrlSettings settings, SharedDictionary`2& customAliasForTabs, Guid parentTraceId)
   at DotNetNuke.Entities.Urls.TabPathHelper.GetTabPath(TabInfo tab, FriendlyUrlSettings settings, FriendlyUrlOptions options, Boolean ignoreCustomRedirects, Boolean homePageSiteRoot, Boolean isHomeTab, String cultureCode, Boolean isDefaultCultureCode, Boolean hasPath, Boolean& dropLangParms, String& customHttpAlias, Boolean& isCustomPath, Guid parentTraceId)
   at DotNetNuke.Entities.Urls.AdvancedFriendlyUrlProvider.ImproveFriendlyUrlWithMessages(TabInfo tab, String friendlyPath, String pageName, PortalSettings portalSettings, Boolean ignoreCustomRedirects, FriendlyUrlSettings settings, List`1& messages, Boolean cultureSpecificAlias, Guid parentTraceId)
   at DotNetNuke.Entities.Urls.AdvancedFriendlyUrlProvider.ImproveFriendlyUrl(TabInfo tab, String friendlyPath, String pageName, PortalSettings portalSettings, Boolean ignoreCustomRedirects, Boolean cultureSpecificAlias, FriendlyUrlSettings settings, Guid parentTraceId)
   at DotNetNuke.Entities.Urls.AdvancedFriendlyUrlProvider.FriendlyUrlInternal(TabInfo tab, String path, String pageName, String portalAlias, PortalSettings portalSettings)
   at DotNetNuke.Entities.Urls.AdvancedFriendlyUrlProvider.FriendlyUrl(TabInfo tab, String path, String pageName, PortalSettings portalSettings)
   at DotNetNuke.Services.Url.FriendlyUrl.DNNFriendlyUrlProvider.FriendlyUrl(TabInfo tab, String path, String pageName, PortalSettings settings)
   at DotNetNuke.Common.Globals.NavigateURL(Int32 tabID, Boolean isSuperTab, PortalSettings settings, String controlKey, String language, String pageName, String[] additionalParameters)
   at DotNetNuke.Common.Globals.NavigateURL(Int32 tabID, String controlKey, String[] additionalParameters)
   at Ventrian.SimpleGallery.RandomPhoto.GetAlbumUrl(String albumID)
   at Ventrian.SimpleGallery.RandomPhoto.BindPhoto(PlaceHolder phPhoto, PhotoInfo objPhoto)
   at Ventrian.SimpleGallery.RandomPhoto.dlGallery_OnItemDataBound(Object sender, DataListItemEventArgs e)
   at System.Web.UI.WebControls.DataList.OnItemDataBound(DataListItemEventArgs e)
   at System.Web.UI.WebControls.DataList.CreateItem(Int32 itemIndex, ListItemType itemType, Boolean dataBind, Object dataItem)
   at System.Web.UI.WebControls.DataList.CreateControlHierarchy(Boolean useDataSource)
   at System.Web.UI.WebControls.BaseDataList.OnDataBinding(EventArgs e)
   at System.Web.UI.WebControls.BaseDataList.DataBind()
   at Ventrian.SimpleGallery.RandomPhoto.Page_Load(Object sender, EventArgs e)

最佳答案

因为您只想知道 Contains 是如何导致越界异常的,下面是如何。

Contains 是这样实现的:

来源取自 http://referencesource.microsoft.com/#mscorlib/system/collections/generic/list.cs,cf7f4095e4de7646

public bool Contains(T item) {
            if ((Object) item == null) {
                for(int i=0; i<_size; i++)
                    if ((Object) _items[i] == null)
                        return true;
                return false;
            }
            else {
                EqualityComparer<T> c = EqualityComparer<T>.Default;
                for(int i=0; i<_size; i++) {
                    if (c.Equals(_items[i], item)) return true;
                }
                return false;
            }
        }

当大小不正确(竞争条件?)时,内部数组访问将抛出异常

关于c# - List.Contains 上的索引越界,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43915717/

相关文章:

C# - 在处理流之前返回内存流字节数组的效果?

c# - 如何在 C# 中将 Dim order(4) 表示为 Int16?

c# - 尝试在 C# 中传递大量字符时尝试读取或写入 protected 内存

c# - 如何为 Entity Framework Code First 迁移设置隔离级别

c# - 最小起订量失败,因为它需要返回值但不让我提供

c# - 单元/集成测试中的反射问题

c# - 从哪里开始使用 C#

c# - .NET 反射 : how to get properties defined on partial class

c# - 包含集合时激活 SoftDelete 数据过滤器

c# - Entity Framework - 尝试插入到带有外键的表中,EF 尝试插入到带有主键的原始表中