List.Contains

时间:2017-05-11 12:41:50

标签: c#

使用(DNN)的CMS中的一段代码会引发以下异常:

"索引超出了数组的范围。"

堆栈跟踪说:

 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;
    }
}

DataCache(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)

2 个答案:

答案 0 :(得分:4)

因为你只想知道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;
            }
        }

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

答案 1 :(得分:3)

我在DNN中打开了一个解决此问题的拉取请求。我们遇到了这个问题,在进行更改后,我们在错误日志中没有看到此堆栈跟踪。

https://github.com/dnnsoftware/Dnn.Platform/pull/1932