gpt4 book ai didi

c# 代码似乎以一种无效的方式进行了优化,使得对象值变为 null

转载 作者:可可西里 更新时间:2023-11-01 07:51:39 24 4
gpt4 key购买 nike

我的以下代码出现了一个奇怪的问题:

var all = new FeatureService().FindAll();
System.Diagnostics.Debug.Assert(all != null, "FindAll must not return null");
System.Diagnostics.Debug.WriteLine(all.ToString()); // throws NullReferenceException

FindAll 方法的签名是:

public List<FeatureModel> FindAll()

通过代码我已经确认 FindAll 的返回值不为空,正如您从断言中看到的那样,“all”变量不为空,但在下一行中它似乎为空。

此问题并非特定于调用 ToString() 方法时失败。在尝试追查根本原因时,我将其简化为这个可重现的示例。

这可能是一个线索:在调试器中,变量“all”出现在 Locals 窗口中,其值为“Cannot obtain value of local or argument 'all' as it is not available at this instruction pointer,可能是因为它已被优化掉。”

我考虑尝试使用其他地方记录的一种方法来禁用代码优化,但这并不能真正解决问题,因为代码的发布版本仍将得到优化。

我正在使用 Visual Studio 2010 和 .NET 4.0。

有什么想法吗?

更新:根据请求,这里是整个方法:

protected override List<FeatureModel> GetModels() {
var all = new FeatureService().FindAll();
var wr = new WeakReference(all);
System.Diagnostics.Debug.Assert(all != null, "FindAll must not return null");
System.Diagnostics.Debug.WriteLine(wr.IsAlive);
System.Diagnostics.Debug.WriteLine(all.ToString()); // throws NullReferenceException
return all;
}

仅供引用,最初的实现很简单:

protected override List<FeatureModel> GetModels() {
return new FeatureService().FindAll();
}

原来是在调用方法中遇到了null异常。我发布的代码是在跟踪问题一段时间后发布的。

更新 #2:根据要求,这里是异常的堆栈跟踪:

 at FeatureCrowd.DomainModel.FeatureSearch.GetModels() in C:\Users\Gary\Documents\Visual Studio 2010\Projects\FeatureCrowd\FeatureCrowd.DomainModel\FeatureSearch.cs:line 32
at FeatureCrowd.DomainModel.FeatureSearch.CreateIndex() in C:\Users\Gary\Documents\Visual Studio 2010\Projects\FeatureCrowd\FeatureCrowd.DomainModel\FeatureSearch.cs:line 42
at FeatureCrowd.DomainModel.FeatureService.CreateSearchIndex() in C:\Users\Gary\Documents\Visual Studio 2010\Projects\FeatureCrowd\FeatureCrowd.DomainModel\FeatureService.cs:line 100
at Website.MvcApplication.BuildLuceneIndexThread(Object sender) in C:\Users\Gary\Documents\Visual Studio 2010\Projects\FeatureCrowd\FeatureCrowd.Website\Global.asax.cs:line 50
at Website.MvcApplication.Application_Start() in C:\Users\Gary\Documents\Visual Studio 2010\Projects\FeatureCrowd\FeatureCrowd.Website\Global.asax.cs:line 61

最佳答案

通过 TeamViewer 查看代码,最后在我自己的机器上下载、编译和运行代码后,我相信这是C# 4.0 中的编译器错误>.


在设法将问题减少到几个简单的项目和文件之后,我发布了一个请求验证的问题。可在此处获得:Possible C# 4.0 compiler error, can others verify?


可能的罪魁祸首不是这个方法:

protected override List<FeatureModel> GetModels() {
var fs = new FeatureService();
var all = fs.FindAll();
var wr = new WeakReference(all);
System.Diagnostics.Debug.Assert(all != null, "FindAll must not return null");
System.Diagnostics.Debug.WriteLine(wr.IsAlive);
System.Diagnostics.Debug.WriteLine(all.ToString()); // throws NullReferenceException
return all;
}

但是它调用的方法,FeatureService.FindAll:

public List<FeatureModel> FindAll() {
string key = Cache.GetQueryKey("FindAll");
var value = Cache.Load<List<FeatureModel>>(key);
if (value == null) {
var query = Context.Features;
value = query.ToList().Select(x => Map(x)).ToList();
var policy = Cache.GetDefaultCacheItemPolicy(value.Select(x => Cache.GetObjectKey(x.Id.ToString())), true);
Cache.Store(key, value, policy);
}
value = new List<FeatureModel>();
return value;
}

如果我从这里更改 GetModels 中的调用:

var all = fs.FindAll();

为此:

var all = fs.FindAll().ToList(); // remember, it already returned a list

然后程序因 ExecutionEngineException 崩溃。


在进行清理、构建,然后通过 Reflector 查看编译后的代码后,输出结果如下(滚动到重要部分代码的底部):

public List<FeatureModel> FindAll()
{
List<FeatureModel> value;
Func<FeatureModel, string> CS$<>9__CachedAnonymousMethodDelegate6 = null;
List<FeatureModel> CS$<>9__CachedAnonymousMethodDelegate7 = null;
string key = base.Cache.GetQueryKey("FindAll");
if (base.Cache.Load<List<FeatureModel>>(key) == null)
{
if (CS$<>9__CachedAnonymousMethodDelegate6 == null)
{
CS$<>9__CachedAnonymousMethodDelegate6 = (Func<FeatureModel, string>) delegate (Feature x) {
return this.Map(x);
};
}
value = base.Context.Features.ToList<Feature>().Select<Feature, FeatureModel>(((Func<Feature, FeatureModel>) CS$<>9__CachedAnonymousMethodDelegate6)).ToList<FeatureModel>();
if (CS$<>9__CachedAnonymousMethodDelegate7 == null)
{
CS$<>9__CachedAnonymousMethodDelegate7 = (List<FeatureModel>) delegate (FeatureModel x) {
return base.Cache.GetObjectKey(x.Id.ToString());
};
}
Func<Feature, FeatureModel> policy = (Func<Feature, FeatureModel>) base.Cache.GetDefaultCacheItemPolicy(value.Select<FeatureModel, string>((Func<FeatureModel, string>) CS$<>9__CachedAnonymousMethodDelegate7), true);
base.Cache.Store<List<FeatureModel>>(key, value, (CacheItemPolicy) policy);
}
value = new List<FeatureModel>();
bool CS$1$0000 = (bool) value;
return (List<FeatureModel>) CS$1$0000;
}

注意该方法的最后 3 行,它们在代码中的样子如下:

value = new List<FeatureModel>();
return value;

Reflector 是这样说的:

value = new List<FeatureModel>();
bool CS$1$0000 = (bool) value;
return (List<FeatureModel>) CS$1$0000;

它创建列表,然后将其转换为 bool 值,然后将其转换回列表并返回。这很可能会导致堆栈问题。

这是相同的方法,在 IL 中(仍然通过 Reflector),我剥离了大部分代码:

.method public hidebysig instance class [mscorlib]System.Collections.Generic.List`1<class FeatureCrowd.DomainModel.FeatureModel> FindAll() cil managed
{
.maxstack 5
.locals init (
[0] string key,
[1] class [mscorlib]System.Collections.Generic.List`1<class FeatureCrowd.DomainModel.FeatureModel> 'value',
[2] class [System.Data.Entity]System.Data.Objects.ObjectSet`1<class FeatureCrowd.DomainModel.Feature> query,
[3] class [mscorlib]System.Func`2<class FeatureCrowd.DomainModel.Feature, class FeatureCrowd.DomainModel.FeatureModel> policy,
[4] class [mscorlib]System.Func`2<class FeatureCrowd.DomainModel.FeatureModel, string> CS$<>9__CachedAnonymousMethodDelegate6,
[5] class [mscorlib]System.Collections.Generic.List`1<class FeatureCrowd.DomainModel.FeatureModel> CS$<>9__CachedAnonymousMethodDelegate7,
[6] bool CS$1$0000,
[7] char CS$4$0001)
...
L_009f: newobj instance void [mscorlib]System.Collections.Generic.List`1<class FeatureCrowd.DomainModel.FeatureModel>::.ctor()
L_00a4: stloc.1
L_00a5: ldloc.1
L_00a6: stloc.s CS$1$0000
L_00a8: br.s L_00aa
L_00aa: ldloc.s CS$1$0000
L_00ac: ret
}

这是一个 screencast showing the debug session ,如果您只想要 Reflector 输出,请跳到大约 2:50。

关于c# 代码似乎以一种无效的方式进行了优化,使得对象值变为 null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3379894/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com